Now Viewing

Blog

basic-freebsd-webserv.md

Setting up a basic web service on FreeBSD 15

Setting up a FreeBSD webserver on Vultr from scratch.

rc.conf:


pf.conf:

sshd_config:

Caddy Setup:

Message from caddy-2.11.3:

--
To enable caddy:

- Edit /usr/local/etc/caddy/Caddyfile
  See https://caddyserver.com/docs/
- Run 'service caddy enable'

Note while Caddy currently defaults to running as root:wheel, it is strongly
recommended to run the server as an unprivileged user, such as www:www --

- Use security/portacl-rc to enable privileged port binding:

  # pkg install security/portacl-rc
  # sysrc portacl_users+=www
  # sysrc portacl_user_www_tcp="http https"
  # sysrc portacl_user_www_udp="https"
  # service portacl enable
  # service portacl start

- Configure caddy to run as www:www

  # sysrc caddy_user=www caddy_group=www

- Note if Caddy has been started as root previously, files in
  /var/log/caddy, /var/db/caddy, and /var/run/caddy may require their ownership
  changing manually.

/usr/local/etc/rc.d/caddy has the following defaults:

- Server log: /var/log/caddy/caddy.log
  (runtime messages, NOT an access.log)
- Automatic SSL certificate storage: /var/db/caddy/data/caddy/
- Administration endpoint: //unix/var/run/caddy/caddy.sock
- Runs as root:wheel (this will change to www:www in the future)

Install Elixir:

root@www:~ # pkg install elixir
Updating FreeBSD-ports repository catalogue...
FreeBSD-ports repository is up to date.
Updating FreeBSD-ports-kmods repository catalogue...
FreeBSD-ports-kmods repository is up to date.
All repositories are up to date.
The following 3 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
    elixir: 1.17.3 [FreeBSD-ports]
    erlang: 26.2.5.16_2,4 [FreeBSD-ports]
    erlang-man: 26.2 [FreeBSD-ports]

Number of packages to be installed: 3

The process will require 134 MiB more space.
51 MiB to be downloaded.

Proceed with this action? [y/N]: y
[1/3] Fetching erlang-man-26.2: 100%  1250 KiB   1.3 MB/s    00:01    
[2/3] Fetching erlang-26.2.5.16_2,4: 100%    40 MiB  42.1 MB/s    00:01    
[3/3] Fetching elixir-1.17.3: 100%  9719 KiB  10.0 MB/s    00:01    
Checking integrity... done (0 conflicting)
[1/3] Installing erlang-man-26.2...
[1/3] Extracting erlang-man-26.2: 100%
[2/3] Installing erlang-26.2.5.16_2,4...
===> Creating groups
Creating group 'beam' with gid '372'
===> Creating users
Creating user 'beam' with uid '372'
[2/3] Extracting erlang-26.2.5.16_2,4: 100%
[3/3] Installing elixir-1.17.3...
[3/3] Extracting elixir-1.17.3: 100%
=====
Message from erlang-26.2.5.16_2,4:

--
Installation tips:

You can find an emacs mode for Erlang here:

    /usr/local/lib/erlang/lib/tools-%%TOOLS_VSN%%/emacs
=====
Message from elixir-1.17.3:

--
Elixir requires a compatible Erlang/OTP runtime. Ensure that you have
one of the following installed:

- lang/erlang
- lang/erlang-runtime24 or newer

Install git-lite:

root@www:~ # pkg install git-lite
Updating FreeBSD-ports repository catalogue...
FreeBSD-ports repository is up to date.
Updating FreeBSD-ports-kmods repository catalogue...
FreeBSD-ports-kmods repository is up to date.
All repositories are up to date.
The following 9 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
    brotli: 1.2.0,1 [FreeBSD-ports]
    curl: 8.20.0 [FreeBSD-ports]
    expat: 2.8.1 [FreeBSD-ports]
    git-lite: 2.53.0 [FreeBSD-ports]
    libnghttp2: 1.68.1 [FreeBSD-ports]
    libpsl: 0.21.5_2 [FreeBSD-ports]
    libssh2: 1.11.1,3 [FreeBSD-ports]
    pcre2: 10.47_1 [FreeBSD-ports]
    zstd: 1.5.7_1 [FreeBSD-ports]

Number of packages to be installed: 9

The process will require 76 MiB more space.
13 MiB to be downloaded.

Proceed with this action? [y/N]: y
[1/9] Fetching libnghttp2-1.68.1: 100%   139 KiB 142.1 kB/s    00:01    
[2/9] Fetching zstd-1.5.7_1: 100%   509 KiB 520.9 kB/s    00:01    
[3/9] Fetching pcre2-10.47_1: 100%  1468 KiB   1.5 MB/s    00:01    
[4/9] Fetching libssh2-1.11.1,3: 100%   244 KiB 249.9 kB/s    00:01    
[5/9] Fetching libpsl-0.21.5_2: 100%    66 KiB  67.5 kB/s    00:01    
[6/9] Fetching curl-8.20.0: 100%  1834 KiB   1.9 MB/s    00:01    
[7/9] Fetching brotli-1.2.0,1: 100%   388 KiB 397.6 kB/s    00:01    
[8/9] Fetching expat-2.8.1: 100%   129 KiB 132.3 kB/s    00:01    
[9/9] Fetching git-lite-2.53.0: 100%  8733 KiB   8.9 MB/s    00:01    
Checking integrity... done (0 conflicting)
[1/9] Installing brotli-1.2.0,1...
[1/9] Extracting brotli-1.2.0,1: 100%
[2/9] Installing expat-2.8.1...
[2/9] Extracting expat-2.8.1: 100%
[3/9] Installing libnghttp2-1.68.1...
[3/9] Extracting libnghttp2-1.68.1: 100%
[4/9] Installing libpsl-0.21.5_2...
[4/9] Extracting libpsl-0.21.5_2: 100%
[5/9] Installing libssh2-1.11.1,3...
[5/9] Extracting libssh2-1.11.1,3: 100%
[6/9] Installing pcre2-10.47_1...
[6/9] Extracting pcre2-10.47_1: 100%
[7/9] Installing zstd-1.5.7_1...
[7/9] Extracting zstd-1.5.7_1: 100%
[8/9] Installing curl-8.20.0...
[8/9] Extracting curl-8.20.0: 100%
[9/9] Installing git-lite-2.53.0...
===> Creating groups
Creating group 'git_daemon' with gid '964'
===> Creating users
Creating user 'git_daemon' with uid '964'
[9/9] Extracting git-lite-2.53.0: 100%
=====
Message from git-lite-2.53.0:

--
If you installed the GITWEB option please follow these instructions:

In the directory /usr/local/share/examples/git/gitweb you can find all files to
make gitweb work as a public repository on the web.

All you have to do to make gitweb work is:
1) Please be sure you're able to execute CGI scripts in
   /usr/local/share/examples/git/gitweb.
2) Set the GITWEB_CONFIG variable in your webserver's config to
   /usr/local/etc/git/gitweb.conf. This variable is passed to gitweb.cgi.
3) Restart server.


If you installed the CONTRIB option please note that the scripts are
installed in /usr/local/share/git-core/contrib. Some of them require
other ports to be installed (perl, python, etc), which you may need to
install manually.

Add blog user for our actual service:

root@www:~ # pw useradd blog -c "Blog Webserver" -s /usr/local/bin/git-shell -m

Add an ssh key for the blog user:

root@www:~ # vim .ssh/authorized_keys
root@www:~ # chown blog:blog .ssh/authorized_keys 
root@www:~ # chmod 600 .ssh/authorized_keys 

Init Bare Repo:

git init --bare /home/blog/repo.git

Note - if you’re doing this as root, you’ll need to make sure to chown and chmod the repository and the authorized_keys files to their appropriate permissions before this will work.

Set up a git target:

joss@grove ~/s/wandering_grove.net (main)> git remote add publish publish.wandering-grove.net:~/repo.git
joss@grove ~/s/wandering_grove.net (main)> git push publish main

Note - if you add publish.wandering-grove.net to your .ssh/config, then you must specify the remote host as above. Trying to target ssh://publish.wandering-grove.net:~/repo.git will not work.

Deployment script from here:

https://gist.github.com/nonbeing/f3441c96d8577a734fa240039b7113db#file-post-receive

Service file from here:

https://elixirforum.com/t/a-simple-rc-d-script-to-run-your-release-as-a-daemon-on-freebsd/66140

Allow the blog user to restart the service in visudo:

blog ALL=(root) NOPASSWD: /usr/sbin/service blog restart

Add to vim /usr/local/etc/newsyslog.conf.d/blog.conf:

/var/log/blog.log  640  7  *  @T00  Z
root@www:~ # cat /usr/local/etc/syslog.d/blog.conf
!blog
*.*    /var/log/blog.log

Install tailwindcss using npm (what a diversion…)

Install caddy & configure:

root@www:/home/blog/worktree # cat /usr/local/etc/caddy/Caddyfile
# The Caddyfile is an easy way to configure your Caddy web server.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace the line below with your
# domain name.

# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
wandering-grove.net, www.wandering-grove.net {
        # Set this path to your site's directory:
        # root * /usr/local/www/caddy

        # Enable the static file server:
        # file_server

        # Set up a reverse proxy:
        reverse_proxy localhost:4000

        # Serve a PHP site through php-fpm:
        # php_fastcgi localhost:9000

        # Enable logging:
        log {
                output file /var/log/caddy/access.log
                # Caddy's structured log format:
                # format json
                format console
                # Or, for Common Log Format:
                # format single_field common_log
        }
}

# Caddy will automatically obtain ACME certs for domains
# example.com {
#     root * /path/to/example.com
#     file_server
# }

# Refer to the Caddy docs for more information:
# https://caddyserver.com/docs/caddyfile

References