Jag vill först och främst adressera anledningen till att jag bytt VPS. Yourserver.se är ett jävla skitföretag, om du har tjänster som behöver vara uppe måste jag starkt avråda från denna oseriösa leverantör av VPS!
Min önskelista för ny VPS är följande:
- Debian 12 istället för Ubuntu server. Snaps är inget jag känner mig hjälpt av, och kurerade stabila paket med bra grundkonfiguration är trevligt.
- VPS placerad inom EU. Den nya ligger i Helsingfors.
- Brandvägg som låser ute all inkommande trafik förutom SSH, HTTP och HTTPS.
- Alla tjänster ska köras via en container eller en Pod, för detta används Podman då det passar mig bättre än Docker.
- Privat Container Registry för att kunna ha allt som behövs för deploy på VPS.
- SSL-certifikat ska skapas och förnyas automatiskt. Detta hanteras med reverse-proxyn Caddy då det blir allt i en lösning, i jämförelse med att köra nginx och certbot.
Först av allt: hantera lösenord och nycklar på ett säkert ställe!¶
Att sätta upp en VPS innebär att flera SSH-nycklar, root-lösenord och andra hemligheter skapas. Se därför till att spara dessa på ett bra och säkert ställe.
Exempelvis:
- 1Password
- LastPass
- Bitwarden
- Keepass
- PWSafe
- Post-It i en skrivbordslåda med lås. Återanvänd inga lösenord!
Välj ett alternativ och ha nära till hands.
Installera paket¶
apt update
apt install \
podman \
ufw \
caddy
Skapa användare¶
Två typer av användare ska finnas på VPS: en användare som äger containern för Container registryt, och en användare för varje tjänst som kör på VPS. I denna artikel kommer jag bara att nämna användarne madrse, den användare som äger denna webbplats.
På detta sätt kan styrkan i att Podman kör containers som rootless.
Generera gärna lösenorden (och SSH-nycklarna) med den valda lösenordshanteraren!
useradd -m -s /bin/bash registry
passwd registry
useradd -m -s /bin/bash madrse
passwd madrse
För smidigare åtkomst, skapa SSH-nycklar och lägg i ~/.ssh/authorized_keys
.
För Debian: Konfigurera och aktivera brandvägg¶
Debian har ingen brandvägg påslagen från start. Debians wiki om UFW är en bra start för att lära sig.
Kör nedanstående som root för att aktivera brandväggen, initialt blockera allt inkommande och tillåta allt utgående. Tilåt därefter enbart inkommande anslutningar av SSH, HTTP och HTTPS.
ufw enable
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow http
ufw allow https
Slutresultatet ska se ut såhär:
root@aginor:~# ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp ALLOW IN Anywhere
[ 2] 80/tcp ALLOW IN Anywhere
[ 3] 443 ALLOW IN Anywhere
För Debian: Tillåt användartjänster att köra även när användare inte är inloggade¶
Debian har som standard att inte tillåta användarens egna daemons och tjänster utanför användarsessioner. För att låta containers köra även när användaren inte är inloggad behöver en inställning ändras i loginctl
.
loginctl enable-linger registry
loginctl enable-linger madrse
Verifiera att användarna har aktiverat:
root@aginor:~/.config/systemd/user$ ls /var/lib/systemd/linger
madrse registry
Sätt upp privat container registry¶
En dedikerad användare har redan skapats för att starta container registryt via en container. Använd denna användare för detta avsnitt, kör ej som root!
Detta avsnitt är baserat på Digital Oceans guide.
Preppa autentisering¶
Glöm inte att spara i lösenordshanteraren!
mkdir -p ~/docker-registry/auth
cd ~/docker-registry/auth
htpasswd -Bc registry.password username
Hämta och starta registry-tjänsten¶
Skapa först katalog.
mkdir -p ~/docker-registry/data
Hämta och starta container registry.
podman run -d \
--name registry \
-p 5000:5000 \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM=Registry \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.password \
-e REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data \
-v '/home/registry/docker-registry/auth:/auth' \
-v '/home/registry/docker-registry/data:/data' \
docker.io/registry:2
Använd podman för att generera systemd-användartjänst, och aktivera den därefter.
mkdir -p .config/systemd/user
(cd .config/systemd/user && podman generate systemd --new --files --name registry)
systemctl --user daemon-reload
systemctl --user enable container-registry
systemctl --user start container-registry
Konfigurera bortstädning av äldre container images¶
För att spara på diskutrymme så konfigureras registryt att bara behålla de 2 senaste pushade versionerna av en container image, och att städa bort alla äldre.
Detta baseras på andrey-pohilko/registry-cli.
För att också städa bort gamla oanvända hämtade containers körs även podman system prune
.
Skapa först cleanup.sh
med följande innehåll. Ersätt inloggningsuppgifterna med de sparade i lösenordshanteraren.
# touch cleanup.sh
# chmod +x cleanup.sh
podman run --rm \
docker.io/anoxis/registry-cli \
-l '<registry username>:<registry password>' \
-r 'https://registry.madr.se' \
--delete \
--num 2
podman system prune -f
Nu kan städning ske när som helst med ssh registry@vps ./cleanup.sh
. För egen del föredrar jag också att skapa en crontab som städar regelbundet, t ex varje lördag morgon.
0 6 * * 6 ~/.cleanup.sh 2>/dev/null 1>&2
Lägg till container registry i Caddyfile¶
Lägg till en reverse proxy för port 5000 för att få HTTPS. Öka även storleken på request_body
så att det går att skicka container images på några hundra MB till registryt.
registry.madr.se {
request_body {
max_size 500MB
}
file_server
reverse_proxy localhost:5000
}
För madr.se¶
Nu är VPS:en redo för den första tjänsten, och det råkar vara denna webbplats. Här är en lista över saker som ska finnas.
- En pod som kör CMS, databas till CMS och webbplatsens WWW-rot.
- Ett par containers i registryt för att kunna göra en deploy, t ex en container med Metalsmith.
- En entry i Caddyfile för att aktivera HTTPS och ge publik åtkomst.
Pusha upp containers¶
Logga först in på container registry.
podman login registry.madr.se
Bygg därefter varje container som behövs och pusha till registry.
podman build .
podman tag <container id> registry.madr.se/madrse-<name>
podman push registry.madr.se/madrse-<name>
Skapa pod och starta containers¶
Inloggad som madr.se-användaren på VPS, skapa pod för att köra alla containers för tjänsten. kör ej som root! Sätt 8055 respektive 1337 är publika portar för CMS och WWW-rot.
podman pod create \
--name madrse \
-p 8055:8055 \
-p 1337:80
Starta därför varje enskild container i poden, para ihop med podden görs med flaggan med --pod=madrse
. Skippa portmappning då poden hanterar detta automatiskt. Lägg också till --replace
för att enkelt kunna ersätta containern med en nyare version. Låt databasens och CMS:ets filer hanteras som volymer för att minska risken för dataförlust!
Såhär görs detta för madr.se. (alla miljövariabler är maskade, kika på respektive tjänsts dokumentation för att se vad som behövs).
podman run -d \
--pod=madrse \
--name=db \
--replace \
-v /home/madrse/directus/data:/var/lib/postgresql/data \
docker.io/postgres:alpine
podman run -d \
--pod=madrse \
--name=directus \
--replace \
-v /home/madrse/directus/uploads:/directus/uploads \
docker.io/directus/directus:10.10.7
podman run -d \
--pod=madrse \
--name=www \
--replace \
registry.madr.se/madrse-w3:latest
Kör pod med systemd¶
Systemd är kontroversiellt, men är fortfarande det fördragna sättet att köra användartjänster kopplade till bootprocessen.
Använd Podman för att generera och aktivera tjänsten.
mkdir -p .config/systemd/user
(cd .config/systemd/user && podman generate systemd --new --files --name madrse)
systemctl --user daemon-reload
systemctl --user enable pod-madrse
systemctl --user start pod-madrse
Lägg till madr.se i Caddyfile¶
CMS och WWW-rot kör på egna subdomäner. För maximal flexibilitet aktiveras även file_server
för enklare felsidor, favikoner etc.
cms.madr.se {
file_server
reverse_proxy localhost:8055
}
madr.se {
file_server
reverse_proxy localhost:1337
}
Städa bort oanvända containers¶
För att inte gamla och ej använda containers med bihang ska ligga och sluka disk, schemalägg ett cronjob som städar. En gång per vecka räcker gott, jag föredrar lördag morgon.
0 6 * * 6 podman system prune -f 2>/dev/null 1>&2
Nästa steg¶
Sammanfattningsvis är detta nu klart. CMS, databas och WWW-rot finns på plats. Skeppande av ny kod sker med push till registryt och en omstart av WWW-rotens container.
Ny deploy av madr.se WWW-rot:
ssh vps podman pull registry.madr.se/madrse-w3:latest
ssh vps podman run -d \
--pod=madrse \
--name=www \
--replace \
registry.madr.se/madrse-w3:latest
För omstart av podden:
ssh vps systemctl --user restart pod-madrse
Det är förmodligen smidigt att automatisera Zero downtime deploy. Detta kan nog bli en egen artikel när jag landat i hur jag vill göra.
Eventuellt kommer jag även skriva om vad som krävdes för att få till Directus att lira med Metalsmith.
Fel och fixar¶
Det händer ibland att skumma fel uppstår, särskilt i centrala delar. I detta avsnitt samlas de jag vet jan uppstå och en lösning till dem.
"Failed to connect to bus: No medium found" vid systemctl --user¶
Kan uppstå vid installation direkt via tty istället för ssh, eller på en användare som skapats under installationsprocessen av Debian. Relaterat till DBUS.
Lägg till i .bashrc
eller motsvarande:
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
eval $(dbus-launch --sh-syntax)
export DBUS_SESSION_BUS_ADDRESS
export DBUS_SESSION_BUS_PID
export XDG_RUNTIME_DIR=/run/user/$(id -u)
fi
Om felet kvarstår, installera följande paket:
apt install dbus-x11
Sidenote: prefixet "-x11" är ren humbug, då detta inte kräver x11. Jag skyller detta på Debian som namngivit illa.