?! HowTheFu.cc ?!
<< SSH: Client Configuration
>> FFMPEG: Quick Commands

2023.10.01
OpenBSD: Setup a Static Website and a Gitea Instance

Resources:

Goals

This write-up is going to cover three things:

I'm not claiming that this is the best way of achieving these goals, but this is the approach I used (at the time of writing) and which have worked for me.

Preparation

I'm assuming OpenBSD has been installed. In my instance, it came pre-installed with the VPS I'm renting. Make sure OpenBSD is up-to-date using:


> sysupgrade  # To get to the next major release. Repeat if necessary.
> syspatch
> pkg_add -Uu
> sysmerge -d    # Shows the changes to be made. Use 'd' to keep _your_ config.
> reboot

Install any quality of life tools now:


> pkg_add fish neovim rsync
Note: If you want to move files onto the server using rsync, OpenBSD needs to have rsync installed as well.

Make sure your domain is configured correctly. This depends on the domain registrar you are using. The config probably looks something like this:


A    Record      *    [IPv4 Address]
A    Record      @    [IPv4 Address]
A    Record    www    [IPv4 Address]
AAAA Record      *    [IPv6 Address]
AAAA Record      @    [IPv6 Address]
AAAA Record    www    [IPv6 Address]

SSH Login

Configure remote logins into the OpenBSD machine by SSH-key authentification. I'm assuming a login into the root user. SSH expects its files and directories to have very specific permissions:

Place the public key of your home machine into /root/.ssh/authorized_keys. Then edit /etc/ssh/sshd_config as follows:


PermitRootLogin yes
Port ???    # Default is 22, but lots of bots will crawl and try to login using that port.
PubkeyAuthorization yes
PasswordAuthentification no
Then restart the SSH service:

> rcctl restart sshd

Configure httpd and acme-client

Setup the website certificates using acme-client: First, copy over the example configuration.


> cp /etc/examples/acme-client.conf /etc/

Then edit the example entry (and do the same for all of your domains / subdomains, e.g. git.howthefu.cc):


domain howthefu.cc {
  alternative names { www.howthefu.cc }
  domain key "/etc/ssl/private/howthefu.cc.key"
  domain full chain certificate "/etc/ssl/howthefu.cc.fullchain.pem"
  sign with letsencrypt
}

domain git.howthefu.cc {
  alternative names { www.git.howthefu.cc }
  domain key "/etc/ssl/private/git.howthefu.cc.key"
  domain full chain certificate "/etc/ssl/git.howthefu.cc.fullchain.pem"
  sign with letsencrypt
}

For your static websites (not Gitea), create the folder which will contain the website contents.


> mkdir /var/www/howthefu.cc

Next, the daemon httpd needs to be configured, as it will serve the website(s). I again first copied over the example file:


> cp /etc/examples/httpd.conf /etc/
And edited the example entries as follows:

# Configure the redirect HTTP -> HTTPS
server * {
        listen on * port 80
        location "/.well-known/acme-challenge/*" {
                root "/acme"
                request strip 2
        }
        location * {
                block return 302 "https://$HTTP_HOST$REQUEST_URI"
        }
}

# Static Website
server "howthefu.cc" {
        listen on * tls port 443
        alias "www.howthefu.cc"

        # Certificates as configured in acme-client.conf
        tls {
                certificate "/etc/ssl/howthefu.cc.fullchain.pem"
                key "/etc/ssl/private/howthefu.cc.key"
        }
        location "/.well-known/acme-challenge/*" {
                root "/acme"
                request strip 2
        }

        # Set the website content to /var/www/howthefu.cc/
        root "/howthefu.cc/"

				# Opional: Disallow hidden files to be served.
	      # Especially useful if you use git to update your site.
	      # Then the .git/ folder (and thus e.g. the commits) are not public.
        location "/.*" { block }
         
        # Optional: On any error, show the file /var/www/howthefu.cc/err/index.html
        errdocs "/howthefu.cc/err/"
}

# Gitea Site
server "git.howthefu.cc" {
        listen on * tls port 443
        alias "www.git.howthefu.cc"
        tls {
                certificate "/etc/ssl/git.howthefu.cc.fullchain.pem"
                key "/etc/ssl/private/git.howthefu.cc.key"
        }
        location "/.well-known/acme-challenge/*" {
                root "/acme"
                request strip 2
        }
        location "/*" {
                fastcgi socket tcp 127.0.0.1 3000
        }
}

Check the config for errors:


> httpd -n
httpd will complain about missing private / public keys, but the command should terminate with configuration OK.

Start the webserver. We need to use -f here because of the previously mentioned missing keys.


> rcctl -f start httpd

Then create the certificates / keys for each site.


> acme-client howthefu.cc
> acme-client git.howthefu.cc

Now we can start httpd properly.


> rcctl -f stop httpd
> rcctl enable httpd
> rcctl start httpd
At this point, the static website should be good to go [0].

Gitea Configuration

Install Gitea. Here I also install bash, as Gitea used to give me errors when bash was not installed on the system (even if I told it to use another shell).


> pkg_add bash gitea

Then configure Gitea to fit with the configuration of httpd by editing /etc/gitea/app.ini as follows:


# Crucial options
[server]
PROTOCOL = fcgi
DOMAIN            = git.howthefu.cc
ROOT_URL          = https://git.howthefu.cc/
STATIC_URL_PREFIX =
HTTP_ADDR         = 127.0.0.1
HTTP_PORT         = 3000

# Additional options I like to use
[server]
SSH_PORT          = ???
LANDING_PAGE      = explore

[service]
REQUIRE_SIGNIN_VIEW  = false

[ui]
DEFAULT_THEME = arc-green

[repository]
ENABLE_PUSH_CREATE_USER = true
DEFAULT_PUSH_CREATE_PRIVATE = true

NOTE: If you want to make to make a repository public (to people without an account), make sure your user is public as well. Otherwise, making the repository "not private" will make it internal, meaning you need to be logged in to view the contents.

Then we can start Gitea using:


> rcctl enable gitea
> rcctl start gitea

Now quickly configure Gitea via your website. After the initial configuration, my Gitea instance looped endlessly when trying to login. Simply restarting the service fixed this for me, and my instance ran just fine afterwards:


> rcctl restart gitea
Don't forget to add your public SSH-keys to your account using the web-interface!

Update Websites and Certificates

The sites need some maintenance:

As I'm pushing my website content onto a git, I can automate both of these problems. Create an accessible script, e.g. /var/www/updateSites.sh.


#!/bin/sh

# Update site content
cd /var/www/howthefu.cc/
/usr/local/bin/git pull -f

# Update certificates
/usr/sbin/acme-client howthefu.cc
/usr/sbin/acme-client git.howthefu.cc

# Restart httpd
/usr/sbin/rcctl reload httpd
And then run this script automatically (i.e. every hour) by creating a cron job using EDITOR=nvim crontab -e and adding the following line:

~       *       *       *       *       /bin/sh /var/www/updateSites.sh
Note that cron is not using your standard $PATH, meaning it has troubles finding commands you can "just" use. You can cirumvent this issue by always specifying the full path of the program you want to run. To locate these tools, run e.g.

> whereis git

Theming Gitea

I like using a non-default Gitea theme. The installation is not that well documented, but it's super simple.

Download a Gitea theme file. It should be a .css file with the naming scheme theme-[Name].css.

Place the theme into /var/gitea/custom/public/assets/css [1]:


> mkdir -p /var/gitea/custom/public/assets/css
> mv theme-pitchblack.css /var/gitea/custom/public/assets/css

Enable the theme in the gitea config by editing /etc/gitea/app.ini as follows:


[ui]
THEMES = auto,gitea,arc-green,pitchblack
DEFAULT_THEME = pitchblack

Restart gitea so the changes take effect.


> rcctl restart gitea

Adjusting Tab-Width

Create the following folder:


> mkdir -p /var/gitea/custom/templates/custom

And then create a file called header.tmpl containing [2]:


<style>
.tab-size-4 {
	tab-size: 2 !important;
	-moz-tab-size: 2 !important;
}
</style>

Restart gitea so the changes take effect.


> rcctl restart gitea

Troubleshooting:

OpenBSD gives you a heads-up when updating gitea. Gitea itself documents breaking changes for each release. Additionally, you can get output for the gitea service by running:


> rcctl -d restart gitea


[0]: I needed to try several things to get my site up and running. I'm not quite sure whether this is necessary, but I have also written down to edit /etc/rc.conf.local as follows:


slowcgi_flags=
httpd_flags=
No idea what that does, so I'm gonna add this as a footnote to this guide in case the instructions above don't work as is.

[1]: This used to be /var/gitea/custom/public/css, but this directory has been changed in release 1.21.0.

[2]: For Gitea 1.18, use .tab-size-8.


<< SSH: Client Configuration
>> FFMPEG: Quick Commands
?! HowTheFu.cc ?!