Systemd Ansible Deployment
ContextUnity defines a 100% native systemd deployment pipeline managed neutrally and idempotently via Ansible configuration management. Docker is strictly deprecated for operational service runtimes inside production deployments, ensuring that your host recovers robustly and performs bare-metal speed native memory management.
Declarative Pipeline
- Host Environment Prep: The
infrastructure/ansiblemodule securely bootstraps your host (LXC, VPS, cloud), installing basic dependencies such asuv, Git, and the optional static PostgreSQL/Redis core infrastructure elements. - ContextUnity Sourcing: The monorepo is idempotently cloned via
git. - Template Segregation: Jinja2 bindings within the Ansible playbook inject target-specific
.env.servicesparameters securely viaAnsible Vault, completely bypassing plaintext configuration disk drops. - Parameterized Service Grids: Dynamic
systemdtemplates iterate to spin up identical processes mapping to variable instance targets (shared,commerce,news).
Systemd Process Orchestration
ContextUnity horizontal scalability pivots directly from native Linux templates @:
ExecStart=/opt/contextunity/services/cu/brain/uv run python -m contextbrainRestart=on-failureRestartSec=5sTimeoutStopSec=30Every service strictly enforces Restart=on-failure policies with a required TimeoutStopSec=30 graceful shutdown capability. ContextUnity routes logging out of native system files to pipe logs exclusively onto journald to natively support global telemetry extraction loops.
Systemd Credentials (Secret Hardening)
ContextUnity supports systemd-creds for encrypting secrets at rest. Instead of storing API keys and encryption keys in plaintext .env files, secrets are encrypted to /etc/credstore.encrypted/ and decrypted at runtime by systemd into CREDENTIALS_DIRECTORY.
How it works
-
Ansible provisions encrypted credentials during deployment:
# In cu_service role — deploy_one.yml- name: Provision encrypted systemd credentialsshell: |echo -n "{{ item.value }}" | systemd-creds encrypt \--name={{ item.name }} - \/etc/credstore.encrypted/{{ svc }}_{{ item.name }}loop: "{{ svc_cfg.credentials | default([]) }}"no_log: true -
Systemd unit loads credentials at service start:
# In service.j2 templateLoadCredentialEncrypted=shield_master_key:/etc/credstore.encrypted/shield_shield_master_key -
Service reads via
_read_credential()fromcontextunity.core.config:from contextunity.core.config import _read_credential# Checks CREDENTIALS_DIRECTORY first, falls back to env varsecret = _read_credential("shield_master_key", os.getenv("SHIELD_MASTER_KEY", ""))
Secret Inventory
| Service | Credential | Env Fallback |
|---|---|---|
| Shield | shield_master_key | SHIELD_MASTER_KEY |
| Shield | shield_encryption_key | SHIELD_ENCRYPTION_KEY |
| Router | cu_project_secret | CU_PROJECT_SECRET |
| Router | redis_secret_key | REDIS_SECRET_KEY |
| Worker | redis_secret_key | REDIS_SECRET_KEY |
| View | django_secret_key | SECRET_KEY |
Ansible Configuration
Define credentials per service in your inventory:
cu_services: shield: credentials: - { name: shield_master_key, value: "{{ vault_shield_master_key }}" } - { name: shield_encryption_key, value: "{{ vault_shield_encryption_key }}" } router: credentials: - { name: cu_project_secret, value: "{{ vault_cu_project_secret }}" } - { name: redis_secret_key, value: "{{ vault_redis_secret_key }}" }Security Hardening
All service units include hardening directives:
NoNewPrivileges=trueProtectSystem=strictReadWritePaths=/tmp /var/log/contextunity /opt/contextunityPrivateTmp=trueCombined with systemd-creds, this ensures secrets are:
- Encrypted at rest on disk (
/etc/credstore.encrypted/, mode0700) - Decrypted only in memory by the service process
- Never visible in
.envfiles, process environment listings, or Ansible logs (no_log: true)