Files
bouncer/docs/DEPLOY.md
user 9954a890c3 docs: add podman deployment guide
New docs/DEPLOY.md covering container image, compose config, volume
mounts, host networking, operations, and troubleshooting. Updated
README, INSTALL, CHEATSHEET, and DEBUG to reference it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:51:29 +01:00

235 lines
4.4 KiB
Markdown

# Podman Deployment
## Overview
The bouncer runs in a rootless podman container with host networking. Source code
and configuration are mounted as volumes -- the container image only contains
Python and pip dependencies.
```
Container (bouncer)
|- python:3.12-slim + deps
|- /app/src <- ./src (read-only volume)
|- /data <- ./config (read-write volume)
```
## Prerequisites
- `podman` and `podman-compose`
- SOCKS5 proxy reachable at `127.0.0.1:1080` (host network)
Verify:
```bash
podman --version
podman-compose --version
ss -tlnp | grep 1080
```
## Quick Start
```bash
cd ~/git/bouncer
# create config from template
cp config/bouncer.example.toml config/bouncer.toml
$EDITOR config/bouncer.toml
# build and start
make build
make up
# check logs
make logs
```
## Container Image
The image installs only runtime dependencies. Source code is not baked in.
```bash
# build
podman build -t bouncer -f Containerfile .
# rebuild after dependency changes
podman build --no-cache -t bouncer -f Containerfile .
```
### Containerfile
```dockerfile
FROM python:3.12-slim
WORKDIR /app
RUN pip install --no-cache-dir \
"python-socks[asyncio]>=2.4" \
"aiosqlite>=0.19"
ENV PYTHONUNBUFFERED=1
ENV PYTHONPATH=/app/src
VOLUME /app/src
VOLUME /data
ENTRYPOINT ["python", "-m", "bouncer"]
CMD ["-c", "/data/bouncer.toml"]
```
## Compose
```yaml
services:
bouncer:
build:
context: .
dockerfile: Containerfile
container_name: bouncer
restart: unless-stopped
network_mode: host
logging:
driver: k8s-file
volumes:
- ./src:/app/src:Z,ro
- ./config:/data:Z
command: ["-c", "/data/bouncer.toml", "-v"]
```
### Volume Mounts
| Host Path | Container Path | Mode | Purpose |
|-----------|---------------|------|---------|
| `./src` | `/app/src` | read-only | Python source code |
| `./config` | `/data` | read-write | Config + SQLite backlog |
The `:Z` suffix applies the correct SELinux context for rootless podman.
### Host Networking
`network_mode: host` is required because the bouncer needs access to:
- `127.0.0.1:1080` -- SOCKS5 proxy (outbound IRC connections)
- `127.0.0.1:6667` -- client listen port (inbound IRC clients)
### Log Driver
`k8s-file` is used instead of the default `journald` driver to ensure
`podman logs` works reliably in rootless mode.
## Operations
### Start / Stop / Restart
```bash
podman-compose up -d # start (detached)
podman-compose down # stop and remove
podman-compose restart # restart
```
Or with make targets:
```bash
make up # podman-compose up -d
make down # podman-compose down
```
### Logs
```bash
podman logs -f bouncer # follow all logs
podman logs --tail 50 bouncer # last 50 lines
podman logs bouncer 2>&1 | grep -v aiosqlite # filter sqlite noise
podman logs bouncer 2>&1 | grep -E 'INFO|WARN' # important events only
```
Or:
```bash
make logs # podman logs -f bouncer
```
### Status
```bash
podman ps --filter name=bouncer
podman inspect bouncer --format '{{.State.Status}}'
```
### Shell Access
```bash
podman exec -it bouncer bash
podman exec bouncer python -c "import bouncer; print(bouncer.__version__)"
```
### Inspect Backlog
The SQLite database is stored in the config volume:
```bash
sqlite3 config/bouncer.db "SELECT network, COUNT(*) FROM messages GROUP BY network;"
```
## Updating
After pulling new code:
```bash
git pull
podman-compose down
podman-compose up -d
```
The image only needs rebuilding if dependencies change:
```bash
podman-compose down
make build
podman-compose up -d
```
## Troubleshooting
### Container exits immediately
Check logs for config or proxy errors:
```bash
podman logs bouncer
```
Common causes:
- Missing `config/bouncer.toml` (not mounted)
- SOCKS5 proxy not running on host
- Invalid TOML syntax
### No log output
Verify `PYTHONUNBUFFERED=1` is set in the Containerfile and the log driver
is `k8s-file`:
```bash
podman inspect bouncer --format '{{.HostConfig.LogConfig.Type}}'
```
### Container can't reach SOCKS5 proxy
`network_mode: host` must be set. Verify the proxy is listening:
```bash
ss -tlnp | grep 1080
```
### Permission denied on volumes
The `:Z` suffix handles SELinux relabeling. If issues persist:
```bash
podman unshare ls -la config/
```
### Rebuild from scratch
```bash
podman-compose down
podman rmi bouncer
podman build --no-cache -t bouncer -f Containerfile .
podman-compose up -d
```