🦭
MitraをRootless Podmanで動かす
MitraをRootless Podmanで動かす。またPodman Quadletを使いサービス化する。
環境
- OS
- AlmaLinux10
- Podman
- 5.4.0
構成
- CaddyServerをリバースプロキシとして使う
- 各コンテナはpodに配置する
- 通信は以下の通り
- internet --80/443--> nftables
- nftables --8080/8443--> caddy
- caddy --8383--> mitra
- Pod間通信: apnet
- mitra --5432--> postgres
- Pod間通信: apnet
AlmaLinuxでRootless Podmanを動かす
- USERのUID/GUIDを設定する
sudo usermod --add-subuids 100000-165536 --add-subgids 100000-165536 $USER
podman system migrate
- nftablesでポートフォワーディングを行う
- Rootless Podmanでは1024番未満のポートは使えないため、 80/443ポートを8080/8443ポートにポートフォワーディングする
table inet nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
tcp dport 80 redirect to :8080
tcp dport 443 redirect to :8443
}
}
- CaddyServerのquic-go関連でエラーがでるので
/etc/sysctl.d/99-sysctl.confに以下を追加
net.core.rmem_max = 7500000
net.core.wmem_max = 7500000
- croupv2関連でエラーが出るので
/etc/systemd/system/user-.slice.d/override.confを編集
[Slice]
Slice=user.slice
CPUAccounting=yes
MemoryAccounting=yes
IOAccounting=yes
TasksAccounting=yes
各コンテナの準備
フォルダ構成
.
└── mitra/
├── conf/
│ └── Caddyfile
├── kube/
│ ├── caddy.yaml
│ ├── mitra.yaml
│ └── postgres.yaml
├── mitra/
│ └── mitra_config.yaml
├── quadlet/
│ ├── apnet.network
│ ├── caddy.kube
│ ├── mitra.kube
│ └── postgres.kube
└── secrets/
└── configmap.yaml
Network
pod間の通信のため
quadlet
- quadlet/apnet.network
[Network]
NetworkName = apnet
PostgresSQL
config
- ConfigMapを設定する
- 本当はSecretsにすべきだが、quadletのkube unitがConfigMapにしか対応していないため
- secrets/configmap.yaml
- ユーザー名・パスワード・データベース名を指定してください
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
data:
user: <username> # FIXME
password: <password> # FIXME
database: <database> # FIXME
encoding: "--encoding=UTF8"
kube
- kube/postgres.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
labels:
app: database-pod
name: database-pod
spec:
containers:
- args:
- postgres
env:
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: postgres-config
key: user
- name: POSTGRES_PASSWORD
valueFrom:
configMapKeyRef:
name: postgres-config
key: password
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: database
- name: POSTGRES_INITDB_ARGS
valueFrom:
configMapKeyRef:
name: postgres-config
key: encoding
image: docker.io/library/postgres:latest # FIXME: specific version
name: postgres
volumeMounts:
- mountPath: /var/lib/postgresql
name: postgres-pvc
- mountPath: /var/lib/postgresql/18/docker # see: https://hub.docker.com/_/postgres#pgdata
name: postgres-data-pvc
volumes:
- name: postgres-pvc
persistentVolumeClaim:
claimName: postgres
- name: postgres-data-pvc
persistentVolumeClaim:
claimName: postgres-data
quadlet
- quadlet/postgres.kube
[Unit]
Description=postgres
[Kube]
Yaml=/home/$USER/mitra/quadlet/postgres.yaml # FIXME: $USER
Network = apnet
ConfigMap=/home/$USER/mitra/secrets/configmap.yaml # FXIME: $USER
[Install]
WantedBy=multi-user.target default.target
[Service]
Delegate = yes
Mitra
config
- mitraの設定
- config.example.yamlを参考に設定する
- データベースの設定はPostgresSQLに合わせて変更する
- mitra/mitra_config.yaml
# Mitra configuration file
# FIXME: username, password, database
database_url: postgres://<username>:<password>@database-pod:5432/<database>
storage_dir: /var/lib/mitra
web_client_dir: /usr/share/mitra/www
http_host: "0.0.0.0"
http_port: 8383
# Log level (debug, info, warn)
log_level: warn
# List of allowed origins for CORS (in addition to `instance_url`)
# Trailing slashes are not allowed.
# 別のクライアントが使うためクライアントのURLを指定する
# http_cors_allow_allのオプションがあるらしい
http_cors_allowlist:
- https://your.example.com
# Domain name
instance_uri: your.example.com
instance_title: example
instance_short_description: my instance
# Long description can contain markdown syntax
instance_description: |
# My instance
Welcome!
registrations_open: false
kube
- bleakfuture0/mitraのコンテナイメージを使う
- kube/mitra.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
bind-mount-options: /home/$USER/mitra/mitra/mitra_config.yaml:z # FIXME: $USER
labels:
app: mitra-pod
name: mitra-pod
spec:
containers:
- image: docker.io/bleakfuture0/mitra:latest
name: mitra
volumeMounts:
- mountPath: /etc/mitra/config.yaml
name: mitra-config
volumes:
- hostPath:
path: /home/$USER/mitra/mitra/mitra_config.yaml # FIXME: $USER
type: File
name: mitra-config
quadlet
- quadlet/mitra.kube
[Unit]
Description=mitra
After=postgres.service
[Kube]
Yaml=/home/$USER/mitra/kube/mitra.yaml # FIXME: $USER
Network = apnet
[Install]
WantedBy=multi-user.target default.target
[Service]
Delegate = yes
ReverseProxy
- Caddyを使う
config
- MitraのReverseProxy設定を参考にする
- conf/Caddyfile
-
caddy fmtをすること
-
{
# Change to your email address for ssl certificate generation
email admin@your.example.com
# Let's setup reasonable logging defaults and target location
log {
level warn
}
}
https://your.example.com {
# Enable response body compression
encode zstd gzip
# Set HSTS headers to improve security posture
header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# Set request body size maximum (This conincides with attachment size. Increase or decrease as you deem necessary)
request_body {
max_size 1MB
}
# Explicit reverse proxy with passing the origin host header to the backend properly
reverse_proxy mitra-pod:8383 {
header_up Host {http.request.host}
}
# Explicit declaration of tls protocols.
tls {
protocols tls1.2 tls1.3
}
}
kube
- kube/caddy.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
bind-mount-options: /home/$USER/mitra/conf:z # FIXME: $USER
labels:
app: reverseproxy-pod
name: reverseproxy-pod
spec:
containers:
- image: docker.io/library/caddy:latest # FIXME: specific version
name: caddy
ports:
- containerPort: 80
hostPort: 8080
- containerPort: 443
hostPort: 8443
- containerPort: 443
hostPort: 8443
protocol: UDP
volumeMounts:
- mountPath: /etc/caddy
name: caddy-conf
- mountPath: /data
name: caddy-data-pvc
- mountPath: /config
name: caddy-config-pvc
volumes:
- hostPath:
path: /home/$USER/mitra/conf # FIXME: $USER
type: Directory
name: caddy-conf
- name: caddy-data-pvc
persistentVolumeClaim:
claimName: caddy-daa
- name: caddy-config-pvc
persistentVolumeClaim:
claimName: caddy-config
quadlet
- quadlet/caddy.kube
[Unit]
Description=caddy
After=mitra.service
[Kube]
Yaml=/home/$USER/mitra/kube/caddy.yaml # FIXME: $USER
PublishPort=8080:80/tcp
PublishPort=8443:443/tcp
PublishPort=8443:443/udp
Network = apnet
[Install]
WantedBy=multi-user.target default.target
[Service]
Delegate = yes
サービス化する
- ログアウト後も起動した状態を保つ
sudo loginctl enable-linger <username>
-
.kubeや.networkファイルを対象のフォルダにコピーして実行- .kubeファイルは一つにまとめられるはずだが、Yamlの指定が分けられなかった
- postgresの起動に時間が少しかかるので分けたほうが良いかも
# podman quadletが読み込むフォルダに.kube, .networkファイルをコピーする
cp ~/mitra/quadlet/* ~/.config/containers/systemd/
# podman v5.6.0以降では`podman quadlet`コマンドを使うことができるが
# 5.4.0ではsystem-generatorを使う
/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun
systemctl --user daemon-reload
systemctl --user start apnet-network.service
systemctl --user start postgres.service
systemctl --user start mitra.service
systemctl --user start caddy.service
- adminユーザーを作成する
podman pod exec -it mitra-pod-mitra mitra create-account <username> <password> admin
その他
- podmanまで使う必要ある?
- オーバーエンジニアリング気味。素直に公式のdpkgファイルをインストールしたほうが楽
- Podmanのマスコットがかわいいので
- オーバーエンジニアリング気味。素直に公式のdpkgファイルをインストールしたほうが楽
- S3への対応は?
Discussion