Service orchestration CLI for OneTimeSecret infrastructure.
Dual-purpose management tool:
- Container orchestration: Containerized OTS deployments via Podman Quadlets (systemd integration)
- Service management: Native systemd services for dependencies (Valkey, Redis)
pipx install git+https://github.com/onetimesecret/ots-containers.gitpip install git+https://github.com/onetimesecret/ots-containers.gitgit clone https://github.com/onetimesecret/ots-containers.git
cd ots-containers
pipx install .ots-containers --help
ots-containers --versionThree container types with explicit systemd unit naming:
| Type | Unit Name | Identifier | Use |
|---|---|---|---|
--web |
onetime-web@{port} |
Port number | HTTP servers |
--worker |
onetime-worker@{id} |
Name/number | Background jobs |
--scheduler |
onetime-scheduler@{id} |
Name/number | Scheduled tasks |
# List all instances
ots-containers instances
ots-containers instances --json
# List by type
ots-containers instances --web
ots-containers instances --worker
ots-containers instances --scheduler
# Deploy instances
ots-containers instances deploy --web 7043 7044
ots-containers instances deploy --worker billing emails
ots-containers instances deploy --scheduler main
# Redeploy (regenerate quadlet and restart)
ots-containers instances redeploy # all running
ots-containers instances redeploy --web 7043 # specific
# Start/stop/restart
ots-containers instances start --web 7043
ots-containers instances stop --scheduler main
ots-containers instances restart # all running
# Status and logs
ots-containers instances status
ots-containers instances logs --web 7043 -f
ots-containers instances logs --scheduler main -f
# Enable/disable at boot
ots-containers instances enable --web 7043
ots-containers instances disable --scheduler main -y
# Interactive shell
ots-containers instances exec --web 7043# Initialize new service instance
ots-containers service init valkey 6379
ots-containers service init redis 6380 --bind 0.0.0.0
# Start/stop/restart
ots-containers service start valkey 6379
ots-containers service stop redis 6380
ots-containers service restart valkey 6379
# Status and logs
ots-containers service status valkey 6379
ots-containers service logs valkey 6379 --follow
# Enable/disable at boot
ots-containers service enable valkey 6379
ots-containers service disable redis 6380
# List available service packages
ots-containers service# Generate basic cloud-init config
ots-containers cloudinit generate > user-data.yaml
# Include PostgreSQL repository
ots-containers cloudinit generate --include-postgresql --postgresql-key /path/to/pgdg.asc
# Include Valkey repository
ots-containers cloudinit generate --include-valkey --valkey-key /path/to/valkey.gpg
# Validate configuration
ots-containers cloudinit validate user-data.yaml# Use a specific image tag
TAG=v0.23.0 ots-containers instances redeploy --web 7043
# Use a different image
IMAGE=ghcr.io/onetimesecret/onetimesecret TAG=latest ots-containers instances deploy --web 7044- Linux with systemd
- Podman installed and configured
- Python 3.11+
FHS-compliant directory structure:
/etc/onetimesecret/ # System configuration
├── config.yaml # Application configuration
├── auth.yaml # Authentication config
└── logging.yaml # Logging config
/etc/default/onetimesecret # Environment file (shared by all instances)
/etc/containers/systemd/ # Quadlet templates (managed by tool)
├── onetime-web@.container
├── onetime-worker@.container
└── onetime-scheduler@.container
/var/lib/onetimesecret/ # Runtime data
└── deployments.db # Deployment timeline (SQLite)
/etc/valkey/ # Valkey system configuration
├── valkey.conf # Default config template
└── instances/ # Instance configs (created by tool)
├── 6379.conf
└── 6379-secrets.conf # Secrets file (mode 0640)
/var/lib/valkey/ # Runtime data
└── 6379/
└── dump.rdb
- Quadlet templates: Writes systemd unit templates to
/etc/containers/systemd/ - Environment: Reads from
/etc/default/onetimesecret - Secrets: Uses Podman secrets for sensitive values
- Timeline: Records deployments to SQLite for audit and rollback
- Config files: Copies package defaults to instance-specific configs
- Secrets: Creates separate secrets files with restricted permissions
- Data directories: Creates per-instance data directories with correct ownership
- systemd: Manages services using package-provided templates
# Check instance status
ots-containers instances status
systemctl status onetime-web@7043
# View logs
ots-containers instances logs --web 7043 -f
journalctl -u onetime-web@7043 -f
# Unified log filtering (all instance types)
journalctl -t onetime -f
# List all onetime systemd units
systemctl list-units 'onetime-*'
# Verify Quadlet templates
cat /etc/containers/systemd/onetime-web@.container
# Reload systemd after manual changes
systemctl daemon-reload# Editable install
git clone https://github.com/onetimesecret/ots-containers.git
cd ots-containers
pip install -e ".[dev,test]"
# Run tests
pytest tests/
# Run with coverage (CI threshold: 70%)
pytest tests/ --cov=ots_containers --cov-fail-under=70
# Pre-commit hooks
pre-commit install# Use full path
sudo /home/youruser/.local/bin/ots-containers instances status
# Or create symlink
sudo ln -s /home/youruser/.local/bin/ots-containers /usr/local/bin/ots-containersMIT