rationale Link to heading

  • docker/podman portable for easy migrations
  • rootless for all except wg-easy needs privileged mode
  • wireguard full tunnel with unbound dns for browsing clients
  • webui for wireguard to add/remove clients easily
  • minimize server exposition by exposing ssh/wireguard only
  • vaultwarden instance for credentials/mfa
  • rustic-server for dedup/encrypted backups
  • caddy as reverse proxy handling automatically certificates
  • service.cloud.domain.tld handled by caddy
  • ssh port forwarding as failover access to services

todo Link to heading

  • using podman secret
  • cleaning compose.yml
  • using api token
  • cleaning Caddyfile

how it looks


context Link to heading

i need of a passwordmanager and backup solution all in one but behind vpn to feel way more secure cool

being able to browse internet while connected to vault solution is mandatory so it’s full tunnel (with dns resolving)

other possible designs : split tunnel / full exposure (novpn) / etc …

prerequisites Link to heading

  • vps/cloud instance
  • A dns registrar resolving *.cloud.domain.tld > vps/instance public ip
  • i use rocky9 with selinux enabled but any distro should do
  • compose.yml are compatible with docker by removing all Zz

firewall Link to heading

firewalld is default on rocky but no need defaults ports

need to open ssh/wireguard and authorize traffic from future wireguard’s clients on 10.8.0.0/24

it is highly recommanded to change ssh’s default :22 port

sudo firewall-cmd --permanent --remove-service=cockpit
sudo firewall-cmd --permanent --remove-service=dhcpv6-client
sudo firewall-cmd --permanent --add-port=MYSSHPORT/tcp
sudo firewall-cmd --permanent --add-port=51820/udp
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.8.0.0/24" accept'
sudo firewall-cmd --complete-reload

if you need to use http-01 challenge (default in caddy ) open http port temporarly each time you generate certs

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --complete-reload

later when caddy do challenge job close it back

sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --complete-reload

otherwise use dns-01 challenge no need to open http port

i prefer using my dns provider api with caddy dns module

users with no privileges Link to heading

  • it’s recommended to use a specific user different from ssh connected user

create a user with no sudo,wheel privileges but give him/her a /home

sudo useradd -m podstack
sudo passwd podstack
sudo loginctl enable-linger podstack

then login

su --login podstack

use a specific directory to handle stack and containers dir/files

mkdir -p vault/caddy/{config,data} vault/rustic/{config,certs,data} vault/{logs,vwdata,wireguard}
cd vault

secrets Link to heading

we use a simple .env file but one can implement podman/dockers secrets or any other vault

~/vault/.env

# Vaultwarden admin token optained with : podman  run --rm -it vaultwarden/server /vaultwarden hash
# then double "$"
VAULTWARDEN_ADMIN_TOKEN=redacted

# Njalla DNS API token
NJALLA_TOKEN=redacted

# WireGuard wg-easy password hash (use $$ to escape $ in YAML, but single $ here in .env)
WG_PASSWORD_HASH=redacted

# WireGuard public IP or hostname
WG_HOST=redcated

vaultwarden Link to heading

enabling signup is ok for creating first user remember to disable it later

i’m not configuring smtp for sending emails to users but it’s trivial to do so

  • compose block
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.cloud.domain.tld"
      TZ: Europe/Paris
      LOG_LEVEL: error
      EXTENDED_LOGGING: true
      LOG_FILE: "/data/vault_access.log"
      ROCKET_PORT: 8080
      WEBSOCKET_ENABLED: false
      ADMIN_TOKEN: ${VAULTWARDEN_ADMIN_TOKEN}
      SIGNUPS_ALLOWED: true
    volumes:
      - ./vwdata:/data:rw,Z
      - ./logs:/data/logs:z
    networks:
      securestack:
        ipv4_address: 10.0.0.3
    expose:
      - "8080"

caddy (building is optionnal) Link to heading

using api i cleaner because no need to open :80 tcp port for http-challenge

no need to build caddy if you’re not using any plugin (dns for example)

building caddy with dns plugins help achieve dns-01 using api

here is build file

~/vault/caddy.build

ARG CADDY_VERSION=latest
FROM caddy:builder AS builder
RUN xcaddy build \
  --with https://github.com/caddy-dns/njalla

FROM caddy:${CADDY_VERSION}
COPY --from=builder /usr/bin/caddy /usr/bin/caddy                          

then we’ll call the build in compose but can force rebuild if needed (update or adding plugins)

compose block

  caddy:
    image: caddy_custom:latest
    container_name: caddy
# build only when plugins are needed
    build:
      context: .
      dockerfile: caddy.build
    restart: unless-stopped
    environment:
      NJALLA_TOKEN: ${NJALLA_TOKEN}
    ports:
# expose 80 only if usng http challenge
#     - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro,Z
      - ./caddy/data:/data:Z
      - ./caddy/config:/config:Z
      - ./logs:/srv/data:z
    networks:
      securestack:
        ipv4_address: 10.0.0.4

Caddyfile is quite simple using common headers for all sites and trying to keep logs for one year (optionnal)

  • reverse proxy and tls handling 3 sites

[https://vault.cloud.domain.tld]

[https://wg.cloud.domain.tld]

[https://rustic.cloud.domain.tld]

  • logging is not mandatory but useful for debugging/reporting/alerting/ids

~/vault/Caddyfile

{
    acme_dns njalla {env.NJALLA_TOKEN}
}
# Common security headers
(header_common) {
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        Referrer-Policy "no-referrer-when-downgrade"
        X-XSS-Protection "1; mode=block"
        Permissions-Policy "geolocation=(), microphone=(), camera=()"
    }
}

(log_common) {
    log {
        format json
        output file /srv/data/{args[0]}_access.log {
            roll_local_time
            roll_size 30mb
            roll_keep 24
            roll_keep_for 365d
        }
    }
}

vault.cloud.domain.tld {
    import header_common
    import log_common vault

    reverse_proxy vaultwarden:8080 {
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
        header_up Host {host}
    }

    encode gzip
}

wg.cloud.domain.tld {
    import header_common
    import log_common wg

    reverse_proxy wg-easy:51821
    encode gzip
}

rustic.cloud.domain.tld {
    import header_common
    import log_common restic

    reverse_proxy rustic-server:8000
    encode gzip
}

wg-easy Link to heading

the only exposed udp port of this stack :51820

webui being reachable on :51821 for vpn connected clients only or via ssh tunneling

wg-easy creates its own config file at start in ~/vault/wireguard/wg0.conf

you should not modify directly this file !

if you need several POST_UP and POST_DOWN rules you can use .env file and call variables as commands

for example

  - WG_POST_UP=echo ${POST_UP} > /etc/wireguard/post-up.txt

dns for wireguard clients (full tunnel) is managed by unbound (optionnal)

generate password with :

docker run ghcr.io/wg-easy/wg-easy:14 wgpw YOUR_PASSWORD

BUT you need to double ‘$’

  • compose block
  wg-easy:
    image: wg-easy/wg-easy
    container_name: wg-easy
    privileged: true
    environment:
      - PASSWORD_HASH=REDACTED
      - WG_HOST=readactedip
      - WG_DEFAULT_DNS=10.0.0.6
      - WG_POST_UP=iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE && iptables -A FORWARD -i wg0 -j ACCEPT && iptables -A FORWARD -o wg0 -j ACCEPT
      - WG_POST_DOWN=iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE && iptables -D FORWARD -i wg0 -j ACCEPT && iptables -D FORWARD -o wg0 -j ACCEPT
      - LANG=en
      - TZ=Europe/Paris
      - UI_TRAFFIC_STATS=true
      - UI_CHART_TYPE=1
    ports:
      - "51820:51820/udp"
      - "127.0.0.1:51821:51821/tcp"
    volumes:
      - ./wireguard:/etc/wireguard:rw,Z
    cap_add:
      - NET_ADMIN
      - NET_RAW
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1
      - net.ipv6.conf.all.disable_ipv6=0
      - net.ipv6.conf.all.forwarding=1
      - net.ipv6.conf.default.forwarding=1
    restart: unless-stopped
    networks:
      securestack:
        ipv4_address: 10.0.0.5

dns unbound Link to heading

a very minimalistic distroless unbound

conf uses quad9 and opennic servers or mullvad’s

~/vault/unbound/unbound.conf

server:
    # Logging - set verbosity to 1 for production, 4 for debugging
    verbosity: 1
    log-file: "/opt/unbound/logs/unbound.log"
    log-queries: no
    log-replies: no
    log-local-actions: yes
    log-servfail: yes
    logfile-limit: 10485760

    # Network
    interface: 0.0.0.0
    port: 53
    do-ip4: yes
    do-ip6: no
    do-udp: yes
    do-tcp: yes

    # Access control - only WireGuard clients and container network
    access-control: 0.0.0.0/0 refuse
    access-control: 10.8.0.0/24 allow
    access-control: 10.0.0.0/24 allow
    access-control: 127.0.0.0/8 allow

    # TLS upstream verification
    tls-cert-bundle: "/etc/ssl/certs/ca-certificates.crt"

    # Identity hiding
    hide-identity: yes
    hide-version: yes
    hide-trustanchor: yes

    # DNSSEC hardening
    harden-glue: yes
    harden-dnssec-stripped: yes
    harden-below-nxdomain: yes
    harden-referral-path: yes
    harden-algo-downgrade: yes
    harden-large-queries: yes
    harden-short-bufsize: yes

    # Query privacy and security
    use-caps-for-id: yes
    qname-minimisation: yes
    qname-minimisation-strict: no
    aggressive-nsec: yes
    val-clean-additional: yes

    # Prevent DNS rebinding attacks
    private-address: 10.0.0.0/8
    private-address: 172.16.0.0/12
    private-address: 192.168.0.0/16
    private-address: 169.254.0.0/16
    private-address: fd00::/8
    private-address: fe80::/10

    # Cache settings
    prefetch: yes
    prefetch-key: yes
    cache-min-ttl: 3600
    cache-max-ttl: 86400
    cache-max-negative-ttl: 300
    msg-cache-slabs: 2
    rrset-cache-slabs: 2
    infra-cache-slabs: 2
    key-cache-slabs: 2
    msg-cache-size: 64m
    rrset-cache-size: 128m

    # Connection limits
    num-threads: 2
    so-reuseport: yes
    incoming-num-tcp: 10
    outgoing-num-tcp: 10
    edns-buffer-size: 1232

    # Rate limiting to prevent abuse
    ip-ratelimit: 200
    ratelimit: 1000

    # Deny ANY queries (often used in amplification attacks)
    deny-any: yes

    # Minimal responses for efficiency
    minimal-responses: yes

    # Unwanted reply threshold
    unwanted-reply-threshold: 10000

forward-zone:
    name: "."
    forward-tls-upstream: yes
    # Quad9 primary (filtered, DNSSEC)
    forward-addr: 9.9.9.9@853#dns.quad9.net
    # Quad9 secondary (filtered, DNSSEC)
    forward-addr: 149.112.112.112@853#dns.quad9.net
    # Quad9 ECS-enabled (filtered, DNSSEC)
    forward-addr: 9.9.9.11@853#dns11.quad9.net
    # Mullvad DNS (no logging, filtered)
    forward-addr: 194.242.2.2@853#dns.mullvad.net

rustic-server Link to heading

need to build rustic-server

~/vault/rustic-server.build

FROM alpine AS builder
ARG RUSTIC_SERVER_VERSION
ARG TARGETARCH
RUN if [ "$TARGETARCH" = "amd64" ]; then \
        ASSET="rustic_server-x86_64-unknown-linux-musl.tar.xz";\
    elif [ "$TARGETARCH" = "arm64" ]; then \
        ASSET="rustic_server-aarch64-unknown-linux-musl.tar.xz"; \
    fi; \
    wget https://github.com/rustic-rs/rustic_server/releases/download/${RUSTIC_SERVER_VERSION}/${ASSET} && \
    tar -xf ${ASSET} --strip-components=1 && \
    mkdir /etc_files && \
    touch /etc_files/passwd && \
    touch /etc_files/group

FROM scratch
COPY --from=builder /rustic-server /rustic-server
COPY --from=builder /etc_files/ /etc/
EXPOSE 8000
ENTRYPOINT ["/rustic-server", "serve"]

you’ll need httpd-tools to generate bcrypt hashed password used for rustic REST authentication

dnf install httpd-tools

create htpasswd file

touch ~/vault/rustic/data/.htpasswd

now create password for each user

htpasswd -B ~/vault/rustic/data/.htpasswd luigi
htpasswd -B ~/vault/rustic/data/.htpasswd brian

create acl.toml file to define permissions of users and groups on repositories

  • for example luigi can Read everything Modify its own repo while brian can only Modify its repo

~/vault/restic/config/acl.toml

[default]
luigi = "Read"

[luigi]
luigi = "Modify"

[brian]
brian = "Modify"
  • compose part
  rustic-server:
    image: rustic-server:latest
    container_name: rustic-server
    build:
      context: .
      dockerfile: rustic-server.build
      args:
        RUSTIC_SERVER_VERSION: "v0.4.0"
        TARGETARCH: "amd64"
    ports:
      - "8000:8000"
    volumes:
      - ./rustic/config:/etc/rustic-server/config:Z
      - ./rustic/certs:/etc/rustic-server/certs:Z
      - ./rustic/data:/var/lib/rustic-server/data:Z
      - ./logs:/var/log/:z
    environment:
      - RUSTIC_SERVER_LISTEN=10.0.0.7:8000
      - RUSTIC_SERVER_DATA_DIR=/var/lib/rustic-server/data
      - RUSTIC_SERVER_QUOTA=0   # 0 means no quota
      - RUSTIC_SERVER_VERBOSE=true
      - RUSTIC_SERVER_DISABLE_AUTH=false
      - RUSTIC_SERVER_HTPASSWD_FILE=/var/lib/rustic-server/data/.htpasswd
      - RUSTIC_SERVER_PRIVATE_REPOS=true
      - RUSTIC_SERVER_APPEND_ONLY=true
      - RUSTIC_SERVER_ACL_PATH=/etc/rustic-server/config/acl.toml
      - RUSTIC_SERVER_LOG_FILE=/var/log/rustic-server.log
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    deploy:
      resources:
        limits:
          memory: 512M
    restart: unless-stopped
    networks:
      securestack:
        ipv4_address: 10.0.0.7

compose file Link to heading

  • to be docker compatible take off z Z

~/vault/podman-compose.yaml

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.cloud.domain.tld"
      TZ: Europe/Paris
      LOG_LEVEL: error
      EXTENDED_LOGGING: true
      LOG_FILE: "/data/vault_access.log"
      ROCKET_PORT: 8080
      WEBSOCKET_ENABLED: false
      ADMIN_TOKEN: REDACTED
      SIGNUPS_ALLOWED: true
    volumes:
      - ./vdata:/data:rw,Z
      - ./logs:/data/logs:z
    networks:
      securestack:
        ipv4_address: 10.0.0.3
    expose:
      - "8080"

  caddy:
    image: caddy_custom:latest
    container_name: caddy
    build:
      context: .
      dockerfile: caddy.build
    restart: unless-stopped
    ports:
# expose :80 only when doing http challenge
#      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro,Z
      - ./caddy/data:/data:Z
      - ./caddy/config:/config:Z
      - ./logs:/srv/data:z
    networks:
      securestack:
        ipv4_address: 10.0.0.4

  wg-easy:
    image: wg-easy/wg-easy
    container_name: wg-easy
    privileged: true
    environment:
      - PASSWORD_HASH=REDACTED
      - WG_HOST=REDACTED_IP
      - WG_DEFAULT_DNS=10.0.0.6
      - WG_POST_UP=iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE && iptables -A FORWARD -i wg0 -j ACCEPT && iptables -A FORWARD -o wg0 -j ACCEPT
      - WG_POST_DOWN=iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE && iptables -D FORWARD -i wg0 -j ACCEPT && iptables -D FORWARD -o wg0 -j ACCEPT
      - LANG=en
      - TZ=Europe/Paris
      - UI_TRAFFIC_STATS=true
      - UI_CHART_TYPE=1
    ports:
      - "51820:51820/udp"
      - "127.0.0.1:51821:51821/tcp"
    volumes:
      - ./wireguard:/etc/wireguard:rw,Z
    cap_add:
      - NET_ADMIN
      - NET_RAW  
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1
      - net.ipv6.conf.all.disable_ipv6=0
      - net.ipv6.conf.all.forwarding=1
      - net.ipv6.conf.default.forwarding=1
    restart: unless-stopped
    networks:
      securestack:
        ipv4_address: 10.0.0.5

  unbound:
    image: klutchell/unbound
    container_name: unbound
    volumes:
      - ./unbound/unbound.conf:/opt/unbound/etc/unbound/unbound.conf:ro,Z
      - ./unbound/root.key:/opt/unbound/etc/unbound/root.key:rw,Z
      - ./logs:/opt/unbound/logs:z
    expose:
      - "53"
    restart: unless-stopped
    networks:
      securestack:
        ipv4_address: 10.0.0.6

  rustic-server:
    image: rustic-server:latest
    container_name: rustic-server
    build:
      context: .
      dockerfile: rustic-server.build
      args:
        RUSTIC_SERVER_VERSION: "v0.11.0"
        TARGETARCH: "amd64"
    expose:
      - "8000"
    volumes:
      - ./rustic/config:/etc/rustic-server/config:Z
      - ./rustic/certs:/etc/rustic-server/certs:Z
      - ./rustic/data:/var/lib/rustic-server/data:Z
      - ./logs:/var/log/:z
    environment:
      - RUSTIC_SERVER_LISTEN=10.0.0.7:8000
      - RUSTIC_SERVER_DATA_DIR=/var/lib/rustic-server/data
      - RUSTIC_SERVER_QUOTA=0   # 0 means no quota
      - RUSTIC_SERVER_VERBOSE=true
      - RUSTIC_SERVER_DISABLE_AUTH=false
      - RUSTIC_SERVER_HTPASSWD_FILE=/var/lib/rustic-server/data/.htpasswd
      - RUSTIC_SERVER_PRIVATE_REPOS=true
      - RUSTIC_SERVER_APPEND_ONLY=true
      - RUSTIC_SERVER_ACL_PATH=/etc/rustic-server/config/acl.toml
      - RUSTIC_SERVER_LOG_FILE=/var/log/rustic-server.log
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    deploy:
      resources:
        limits:
          memory: 512M
    restart: unless-stopped
    networks:
      securestack:
        ipv4_address: 10.0.0.7

networks:
  securestack:
    name: "securestack"
    driver: bridge
    ipam:
      config:
        - subnet: 10.0.0.0/24

starting stack

podman-compose up -d

ssh failover Link to heading

in case something goes wrong with wireguard access via ssh (port forwarding) is easy

enable AllowTcpForwarding in sshd_config

sudo sed -i '/^#*AllowTcpForwarding/ s/^#*AllowTcpForwarding.*/AllowTcpForwarding yes/; t; $ a AllowTcpForwarding yes' /etc/ssh/sshd_config

restart sshd

sudo systemctl restart sshd
  • on your client modify /etc/hosts with 127.0.0.1 vault.cloud.domain.tld
sudo sed -i 's/^127\.0\.0\.1 .*/127.0.0.1 vault.cloud.domain.tld/' /etc/hosts

to reach vaultwarden

ssh -L 8080:127.0.0.1:443 user@vpsip

https://vault.cloud.domain.tld

bitwarden client Link to heading

gnu/linux clients tested

  • cli 2025.5.0
  • bitwarden official (flatpak) 2025.5.1
  • chrome extension 2025.5.1

install bw cli

raw style

curl -sL "https://vault.bitwarden.com/download/?app=cli&platform=linux" -o /tmp/bw.zip
unzip -o /tmp/bw.zip -d /usr/local/bin/
chmod +x /usr/local/bin/bw

or flatpak style

flatpak install flathub com.bitwarden.desktop

then

edit your bash or zsh aliases

alias bw='flatpak run --command=bw com.bitwarden.desktop'

set it up

bw config server https://vault.cloud.domain.tld
bw login

export your temporary session token to be able to do operations without password

import firefox passwords

in firefox go to about:logins then export your logins as .csv

bw import firefoxcsv passwords.csv 

restic/rustic clients Link to heading

via rustic cli

cargo install rustic
mkdir -p ~/config/rustic

with this conf we define earlier generated password server side with htpasswd for rest authentication

  • this is not the backup encryption passwod. user will define it at init

  • you can use other solution than bw cli for storing password as variable

~/.config/rustic/rustic.toml

[repository]
repository = "rest:https://rustic.cloud.domain.tld/lab"
[repository.options]
rest-user = "lab"
rest-password-command = "bw get password rustic-rest-lab"
rustic init

troubleshooting Link to heading

few commands to troubleshoot podman

podman ps
podman network ls
podman network inspect securestack
podman logs -f container1

check overall stack performances

podman stats 
ID            NAME           CPU %       MEM USAGE / LIMIT  MEM %       NET IO          BLOCK IO    PIDS        CPU TIME    AVG CPU %
4b42efa562d2  caddy          0.91%       14.32MB / 1.688GB  0.85%       3.772kB / 558B  0B / 0B     8           56.451ms    0.91%
8c289faab24c  wg-easy        4.74%       18.06MB / 1.688GB  1.07%       3.03kB / 938B   0B / 0B     12          283.46ms    4.74%
df06db0c8be9  vaultwarden    1.06%       9.269MB / 1.688GB  0.55%       4.03kB / 628B   0B / 0B     14          68.2ms      1.06%
1c0d1d518dbe  unbound        1.23%       14.05MB / 1.688GB  0.83%       7.528kB / 936B  0B / 0B     1           71.409ms    1.23%
dd8508634e3b  rustic-server  0.33%       1.729MB / 536.9MB  0.32%       2.814kB / 628B  0B / 0B     3           18.363ms    0.33%

invoke a shell in container

podman exec -it vaultwarden /bin/sh

since pasta version and podman version i got this error

[caddy] | Error: unable to start container 5c1ff1aa3e1c761b838b235709a454d43a7352c277e5759839d0dd1cf5056ec3: setting up Pasta: pasta failed with exit code 1:
[caddy] | Couldn't open PID file /tmp/poduser-runtime/containers/networks/rootless-netns/rootless-netns-conn.pid: Permission denied
[caddy] |

because of selinux

sudo ausearch -m avc -ts recent
time->Thu Jun 19 20:32:29 2025
type=AVC msg=audit(1750357949.492:579): avc:  denied  { add_name } for  pid=3278 comm="pasta.avx2" name="rootless-netns-conn.pid" scontext=unconfined_u:unconfined_r:pasta_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:container_var_run_t:s0 tclass=dir permissive=0
----
time->Thu Jun 19 20:33:22 2025
type=AVC msg=audit(1750358002.688:597): avc:  denied  { create } for  pid=3405 comm="pasta.avx2" name="rootless-netns-conn.pid" scontext=unconfined_u:unconfined_r:pasta_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:container_var_run_t:s0 tclass=file permissive=0
----
time->Thu Jun 19 20:33:28 2025
type=AVC msg=audit(1750358008.406:602): avc:  denied  { create } for  pid=3494 comm="pasta.avx2" name="rootless-netns-conn.pid" scontext=unconfined_u:unconfined_r:pasta_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:container_var_run_t:s0 tclass=file permissive=0
----
time->Thu Jun 19 20:34:35 2025
type=AVC msg=audit(1750358075.265:621): avc:  denied  { write open } for  pid=3606 comm="pasta.avx2" path="/tmp/poduser-runtime/containers/networks/rootless-netns/rootless-netns-conn.pid" dev="tmpfs" ino=234 scontext=unconfined_u:unconfined_r:pasta_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:container_var_run_t:s0 tclass=file permissive=0
----
time->Thu Jun 19 20:34:42 2025
type=AVC msg=audit(1750358082.616:665): avc:  denied  { write } for  pid=3715 comm="pasta.avx2" name="rootless-netns-conn.pid" dev="tmpfs" ino=234 scontext=unconfined_u:unconfined_r:pasta_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:container_var_run_t:s0 tclass=file permissive=0

i needed to adapt selinux

sudo ausearch -c 'pasta.avx2' --raw | sudo audit2allow -M mypasta
sudo semodule -i mypasta.pp
sudo chcon -R -t container_var_run_t /tmp/poduser-runtime

ressources Link to heading

  • vaultwarden

https://github.com/kagiko/vaultwarden-wiki/blob/master/Using-Podman.md

https://mijo.remotenode.io/posts/tailscale-caddy-docker/

https://github.com/kagiko/vaultwarden-wiki/blob/master/Running-a-private-vaultwarden-instance-with-Let's-Encrypt-certs.md

https://github.com/dani-garcia/vaultwarden/discussions/4531

https://github.com/kagiko/vaultwarden-wiki/blob/master/SMTP-Configuration.md#using-sendmail-without-docker

https://github.com/dani-garcia/vaultwarden/blob/main/.env.template

https://github.com/dani-garcia/vaultwarden/wiki/Caddy-2.x-with-Cloudflare-DNS

https://github.com/dani-garcia/vaultwarden/wiki/Running-a-private-vaultwarden-instance-with-Let%27s-Encrypt-certs

https://github.com/kagiko/vaultwarden-wiki/blob/master/Proxy-examples.md

  • wg-easy

https://wg-easy.github.io/wg-easy/Pre-release/examples/tutorials/podman-nft/

https://www.procustodibus.com/blog/2022/10/wireguard-in-podman/#network-mode-with-podman-compose

https://github.com/wg-easy/wg-easy/blob/master/docker-compose.yml

  • rustic-server

https://github.com/rustic-rs/rustic_server/tree/main/containers

https://github.com/rustic-rs/rustic_server/blob/main/USAGE.md

https://rustic.cli.rs/docs/commands/init/rest.html

https://rustic.cli.rs/docs/getting_started.html

  • ansible deploy

https://github.com/guerzon/ansible-role-vaultwarden/tree/main

https://helgeklein.com/blog/vaultwarden-setup-guide-with-automatic-https/