Suite à la réflexion sur mon auto-hébergement, je cherche un solution pour simplifier celui-ci.
Actuellement, je dispose de 3 serveurs:
=> total: 8 vcpu / 14GB RAM / 70GB
=> cout: 28.31€ TTC/mois
Les applications utilisées sont:
tout est déployé en container via kustomize sur k3s.
LXC / KVM
Visiblement, on peut faire beaucoup de chose avec LXC directement. L'idée pourrait être d'avoir un host Debian (ou ubuntu) qui sert d'"hyperviseur" lxc.
Il est possible de lancer des containers podman (ou même docker) dans lxc.
Sur une Debian11:
apt install snapd
snap install lxd
# pour mettre à jour son $PATH
. /etc/profile.d/apps-bin-path.sh
# initialisation en laissant la plupart des valeurs par défaut
lxd init
# créé un container debian database et containers
lxc launch images:debian/bullseye database
lxc launch images:debian/bullseye containers
# pour utiliser podman il faut le security.nest
lxc config set containers security.nesting true
# pour entrée dans un container
lxc exec containers /bin/bash
dans le container "containers":
apt install podman
adduser --disabled-password --shell /bin/bash --gecos "User" pm
su - pm
podman run --rm -it docker.io/library/busybox
pour k3s c'est plus compliqué. J'ai tenté avec cette doc mais k3s ne démarre pas car il ne parvient pas à écrire dans le fichier /proc/sys/vm/overcommit_memory
au démarrage.
Je pense que rester sur une version container podman ou podman-compose est suffisant. C'était surtout pour la partie traefik + certbot.
J'ai testé l'installation de cockpit sans encombre. Peut être intéressant de l'installer dans un container lxc admin qui se connecte à tous les containers lxc de l'hôte. Petite vigilance aux ressources nécessaires pour cockpit.
/boot
primary : 1Go/swap
primary : 8Go/
lv le reste 510Goil est nécessaire d'avoir une partition primaire pour avoir le swap en primaire.
root@hereva:~# lxd init
Would you like to use LXD clustering? (yes/no) [default=no]:
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]:
Name of the storage backend to use (btrfs, ceph, cephobject, dir, lvm) [default=btrfs]:
Create a new BTRFS pool? (yes/no) [default=yes]:
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]:
Size in GiB of the new loop device (1GiB minimum) [default=30GiB]:
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=lxdbr0]:
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
Would you like the LXD server to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:
après avoir installé lxd, je pense que la taille du new loop device est trop petite. il faudrait voir pour la redimenssionner avant de passer en production.
Après quelques avancées, le choix de btfrs n'est pas forcément judicieux. Création d'un nouveau storage lvm
afin d'être plus à l'aise pour les manipulations.
lxc storage create lvm lvm source=/var/snap/lxd/common/lxd/disks/lvm.img
pour migrer un container:
lxc stop <container_name>
lxc move <container_name> <tmp_container_name> -s lvm
lxc move <tmp_container_name> <container_name>
lxc start <container_name>
il permettra d'avoir les outils d'administration et de configuration des autres containers lxc. ansible par exemple. l'objectif est qu'il soit le point d'entrée unique.
comment y accède t-on?
il s'agit d'un point d'entrée extérieur des différentes applications. C'est lui qui aura en charge les reverse proxy https mais également des autres composants tcp (gemini, owncast...)
à décider si haproxy ou nginx ou traefik?
exemple de conf avec haproxy sur un whoami:
frontend http-default
bind :80 accept-proxy
default_backend whoami
backend whoami
option forwardfor
server server1 containers.lxd:8080 check
pour un bon fonctionnement avec certificat:
frontend tls
bind :443 accept-proxy ssl crt /etc/haproxy/certs ssl-min-ver TLSv1.2
use_backend gitea if { req.hdr(host) -i git.valvin.fr }
use_backend owncast if { req.hdr(host) -i live.valvin.fr }
use_backend li if { req.hdr(host) -i li.valvin.fr }
use_backend wallabag if { req.hdr(host) -i wallabag.valvin.fr }
use_backend ttrss if { req.hdr(host) -i rss.valvin.fr }
use_backend rssbridge if { req.hdr(host) -i rssbridge.valvin.fr }
use_backend wikijs if { req.hdr(host) -i wiki.valvin.fr }
use_backend gemlog if { req.hdr(host) -i gmi.valvin.fr }
default_backend gemlog
backend gitea
mode http
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option forwardfor
server server1 podman-apps.lxd:3000 check
pour la génération de certificat, utilisation de certbot + certbot-gandi:
apt install certbot python3-certbot-dns-gandi cron
pour gandi un simple fichier gandi.ini
:
vim /etc/letsencrypt/gandi.ini
# live dns v5 api key
dns_api_key=xxxxx
et pour créer un certificat:
certbot certonly -m <email@domain.tld> --agree-tos --authenticator dns --dns-credentials /etc/letsencrypt/gandi.ini -d <sub.domain.tld>
pour haproxy, il est nécessaire de fusionner fullchain.pem et privkey.pem:
cd /etc/letsencrypt/live/<sub.domain.tld>
cat fullchain.pem privkey.pem > haproxy.pem
Pour gérer plusieurs domaines, on peut mettre tous les certificats dans le même répertoire et laisser haproxy prendre celui qui correspond à partir du sni.
exemple de config avec gitea + owncast:
frontend tls
bind :443 accept-proxy ssl crt /etc/haproxy/certs ssl-min-ver TLSv1.2
use_backend gitea if { req.hdr(host) -i git.valvin.fr }
use_backend owncast if { req.hdr(host) -i live.valvin.fr }
default_backend gitea
backend gitea
option forwardfor
server server1 podman-apps.lxd:3000 check
backend owncast
option forwardfor
server server1 podman-apps.lxd:8080 check
instance postgreSQL
execution des différents containers docker à l'aide de podman.
après quelques tests, la version fournie dans debian11 n'est pas suffisamment récente pour une bonne prise en charge avec podman-compose
. afin de rester sur une version debian like, je pense utiliser une image ubuntu/22.10
. Ce n'est pas du LTS mais l'image ubuntu/focal
ne permet pas d'installer podman nativement.
l'utilisation de podman
+ podman-compose
est opérationnelle mais la commande podman-compose up -d
coupe les containers après arrêt de la session SSH.
Tentative avec podman.socket
+ docker-compose
en cours.
Paquets supplémentaires:
# via pip plutôt qu'apt pour ne pas avoir docker d'installé
pip3 install docker-compose
# pour "wrapper" docker avec des commandes docker
apt install podman-docker
en tant que l'utilisateur podman
systemctl enable --now --user podman.socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
docker-compose up -d
il est également possible de générer un service systemd avec podman generate systemd
.
Après quelques tentatives, la solution docker-compose ou podman-compose n'est peut être pas la bonne idée. Je pense m'orienter vers une création via les modules ansible: https://docs.ansible.com/ansible/latest/collections/containers/podman/podman_container_module.html#ansible-collections-containers-podman-podman-container-module
une des raisons pour lesquelles j'ai rencontré des difficultés est que par défaut un utilisateur ne peut avoir de process en tâche de fond si celui-ci n'est pas loggué. Pour cela, il est nécessaire d'activer le linger avec :
loginctl enable-linger podman
utilisation d'ufw
pour filtrer le réseau entre les containers.
règle basique ufw, à vérifier que les connexions entrantes sont bien bloquées par défaut:
apt install ufw
ufw allow ssh
ufw allow http
ufw allow https
ufw default deny incoming
ufw default allow outgoing
# to allow containers routing
ufw allow in on lxdbr0
ufw route allow in on lxdbr0
ufw enable
pour les redirections vers les containers on peut le faire avec ce paramétrage:
lxc config device add network http-redirect proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80 proxy_protocol=true
lxc config device add network http-redirect proxy listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:433 proxy_protocol=true
# pour gitea
lxc config device add podman-apps ssh-redirect proxy listen=tcp:0.0.0.0:2222 connect=tcp:127.0.0.1:2222 proxy_protocol=true
tout ce qui arrive sur le port 80 est envoyé au container network sur localhost:80. l'option proxy_protocol=true
nécessite que le serveur distant accepte le protocol proxy.
pour mémo, beaucoup de temps passer sur le ssh de gitea. La raison du non fonctionnement était le type de clé généré et la configuration côté client. ssh-rsa n'étant plus supporté par défaut.
utiliser s3fs
n'est pas une bonne idée. l'objectif est uniquement de synchroniser mes backups. pour cela la commande s3cmd
est plus approprié.
s3cmd sync --delete-removed /opt/backup s3://valvin-backup-hereva/database.lxd/
il faut avoir un fichier de config dans le home directory .s3cfg
:
[default]
signature = s3v4
# Object Storage Region FR-PAR
bucket_location = fr-par
host_base = s3.fr-par.scw.cloud
host_bucket = %(bucket).s3.fr-par.scw.cloud
use_https = True
# Login credentials
access_key = <access_key>
secret_key = <secret_key>