Running services
I'm running the following HTTP-based web services on my server:
- Caddy as reverse proxy, terminates SSL and routes to other services
- Apache2 with some mods (like CGI) as web server for the homepage
- Navidrome for the music streaming service
- Gitea as the git server
- Immich for the photo/video management solution
- SearXNG for the aggregated search service
- OpenCloud for the file server
Additionally, I'm running a mail server via Postfix and Dovecot, and an ad-blocking DNS server
(Pi-hole). As the firewall, I'm using
ufw
– though note that there's another firewall on the router.
Service setups
Caddy
, apache2
, ufw
,
postfix
, and dovecot
run directly on the
machine, installed as system packages. The rest runs as podman
containers, via a
bunch of podman-compose.yml
files that expose the services'
plain-text HTTP interfaces on some port only to localhost, e.g.
127.0.0.1:9000
. Adding new web services is just a matter of
spinning up new containers and telling caddy
to
reverse-proxy incoming traffic for some subdomain to their HTTP port.
Scheduling a crontab (1)
job to update the container images
periodically (e.g. weekly) might also be a good idea.
Lingering users
In case the system uses systemd-logind
for managing
login sessions, systemd
will kill all of a user's processes
(via a per-user scope
unit) when they log out. This
obviously interferes with some utilities that are meant to outlast a
login session, like tmux
or podman
containers.
Luckily, there's a way out by telling systemd-logind
to
start a user manager for individual users at boot that is kept around
after logouts: loginctl enable-linger ${username}
Punching pi-holes
To allow pi-hole
to act as a DNS server, I had to stop
systemd-resolved
from listening to port 53
by
setting DNSStubListener=no
in
/etc/systemd/resolved.conf
.
Custom ufw
rules
Because podman
typically runs as an unprivileged user,
using port 53
(which is pretty much required for DNS
servers) is out of the question by default. Instead, I've added an
iptables
redirect via the ufw
config – similar
to the approach from this
blog post. On my server, I added a few lines to the top of
/etc/ufw/before.rules
, under the "*nat
"
section:
# redirect port 53 to 5353 (pi-hole)
:PREROUTING ACCEPT [0:0]
-A PREROUTING -p tcp --dport 53 -j REDIRECT --to-port 5353
-A PREROUTING -p udp --dport 53 -j REDIRECT --to-port 5353
COMMIT
To be on the safe side, I also allowed the port:
sudo ufw allow 5353
Extra virgin snakeoil
I've symlinked /etc/ssl/{certs,private}
and
/etc/dovecot/private
, pointing to
~caddy/.local/share/certificates/.../max-moser.dev/...
, to
give postfix
and dovecot
access to actually
valid certs instead of self-signed snakeoil certificates. Give Google
Mail & co one reason less to junk-jail your emails.
Some fresh software
Debian and Ubuntu aren't exactly known to be bleeding edge
distributions; it's quite common that the versions of packages are a bit
dated (if they're available at all). Neither jless
nor
yazi
are available, and the version of rust
is
too old to compile them from source. Luckily, this can be sidestepped by
installing rustup
with apt
and using that to
install the latest version of rust
, which in turn can be
used to easily cargo install
the desired commands.
Editing files on the server
I've found that editing files on the server with good old
vim
can be a bit of a slog, I actually miss the LSP
integration from my nvim
setup! Fortunately,
sshfs (1)
exists and can solve this exact problem. Mounting
the server's file system to a local directory server-mount
is as simple as this command:
sshfs -o follow_symlinks user@server: ./server-mount