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>
This commit is contained in:
user
2026-02-19 18:51:29 +01:00
parent 48459c8506
commit 9954a890c3
5 changed files with 312 additions and 1 deletions

View File

@@ -52,12 +52,26 @@ IRC Client(s) --> [bouncer:6667] --> Router --> [SOCKS5:1080] --> IRC Server(s)
4. Joins configured channels 4. Joins configured channels
5. Clients connect to bouncer, receive backlog replay and channel state 5. Clients connect to bouncer, receive backlog replay and channel state
## Podman Deployment
```bash
cp config/bouncer.example.toml config/bouncer.toml
$EDITOR config/bouncer.toml
make build
make up
make logs
```
See [docs/DEPLOY.md](docs/DEPLOY.md) for full container documentation.
## Documentation ## Documentation
| Document | Description | | Document | Description |
|----------|-------------| |----------|-------------|
| [docs/INSTALL.md](docs/INSTALL.md) | Prerequisites and setup | | [docs/INSTALL.md](docs/INSTALL.md) | Prerequisites and setup |
| [docs/USAGE.md](docs/USAGE.md) | Comprehensive guide | | [docs/USAGE.md](docs/USAGE.md) | Comprehensive guide |
| [docs/DEPLOY.md](docs/DEPLOY.md) | Podman container deployment |
| [docs/CHEATSHEET.md](docs/CHEATSHEET.md) | Quick reference | | [docs/CHEATSHEET.md](docs/CHEATSHEET.md) | Quick reference |
| [docs/DEBUG.md](docs/DEBUG.md) | Troubleshooting | | [docs/DEBUG.md](docs/DEBUG.md) | Troubleshooting |

View File

@@ -9,6 +9,21 @@ bouncer --version # version
bouncer --help # help bouncer --help # help
``` ```
## Podman
```bash
make build # build container image
make up # podman-compose up -d
make down # podman-compose down
make logs # podman logs -f bouncer
```
```bash
podman logs bouncer 2>&1 | grep -E 'INFO|WARN' # filtered logs
podman exec -it bouncer bash # shell into container
podman ps --filter name=bouncer # status
```
## Develop ## Develop
```bash ```bash

View File

@@ -123,3 +123,41 @@ bouncer -c config/bouncer.toml -v 2>&1 | grep -v aiosqlite
``` ```
The `grep -v aiosqlite` filters out noisy SQLite debug lines. The `grep -v aiosqlite` filters out noisy SQLite debug lines.
## Container Debugging
### Logs
```bash
podman logs -f bouncer # follow
podman logs --tail 50 bouncer # last 50 lines
podman logs bouncer 2>&1 | grep -E 'INFO|WARN' # important only
podman logs bouncer 2>&1 | grep -v aiosqlite # filter sqlite noise
```
### No log output from container
Two things must be set:
1. `PYTHONUNBUFFERED=1` in the Containerfile
2. `logging: driver: k8s-file` in compose.yaml
Verify log driver:
```bash
podman inspect bouncer --format '{{.HostConfig.LogConfig.Type}}'
```
### Container exits immediately
```bash
podman logs bouncer
```
Likely causes: missing config file, SOCKS5 proxy not running, TOML syntax error.
### Shell into running container
```bash
podman exec -it bouncer bash
```

234
docs/DEPLOY.md Normal file
View File

@@ -0,0 +1,234 @@
# 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
```

View File

@@ -5,7 +5,17 @@
- Python 3.10+ - Python 3.10+
- SOCKS5 proxy running on `127.0.0.1:1080` - SOCKS5 proxy running on `127.0.0.1:1080`
## Setup ## Container Deployment (Recommended)
See [DEPLOY.md](DEPLOY.md) for full podman/container instructions.
```bash
cp config/bouncer.example.toml config/bouncer.toml
$EDITOR config/bouncer.toml
make build && make up
```
## Local Setup
```bash ```bash
cd ~/git/bouncer cd ~/git/bouncer