{"id":47305054,"url":"https://github.com/zeslava/dail","last_synced_at":"2026-04-02T19:07:38.558Z","repository":{"id":341064149,"uuid":"1167008444","full_name":"zeslava/dail","owner":"zeslava","description":"Daily jail management for FreeBSD","archived":false,"fork":false,"pushed_at":"2026-03-24T21:24:07.000Z","size":201,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T01:23:56.260Z","etag":null,"topics":["dail","freebsd","jail"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zeslava.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-25T21:08:59.000Z","updated_at":"2026-03-25T16:08:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zeslava/dail","commit_stats":null,"previous_names":["zeslava/dail"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/zeslava/dail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeslava%2Fdail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeslava%2Fdail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeslava%2Fdail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeslava%2Fdail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zeslava","download_url":"https://codeload.github.com/zeslava/dail/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeslava%2Fdail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31313934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dail","freebsd","jail"],"created_at":"2026-03-17T07:54:38.296Z","updated_at":"2026-04-02T19:07:38.544Z","avatar_url":"https://github.com/zeslava.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dail\nDaily jail management for FreeBSD\n\n## Features\n\n- **Familiar workflow:** `create`, `start`, `stop`, `rm`, `run`, `exec`, `build`\n- **`.dail` files:** declarative jail builds\n- **Presets:** one flag to configure common workloads (`--preset postgres`)\n- **Thick \u0026 thin jails:** full copy or shared base with per-jail overlay\n- **Networking:** inherit, IP alias, or VNET with bridge\n- **Port forwarding:** `-p host_port:jail_port` via PF rdr anchors\n- **ZFS support:** snapshots, clones, ZFS-backed storage\n- **Resource limits:** rctl-based CPU/memory/process limits\n\n## Getting Started\n\n```bash\n# 1. Install dail\ncargo build --release\ndoas install -m 755 target/release/dail /usr/local/bin/dail\n\n# 2. Initialize (creates /var/db/dail/, writes default config)\ndoas dail config init\n\n# 3. Download FreeBSD base\ndoas dail bootstrap\n\n# 4. Run your first jail\ndoas dail run myjail\n\n# 5. Open a shell inside\ndoas dail shell myjail\n\n# 6. Stop and remove\ndoas dail stop myjail\ndoas dail rm myjail\n```\n\n## Examples\n\n### PostgreSQL\n\n```dockerfile\n# postgres.dail\nFROM 15.0-RELEASE\n\nPARAM allow.sysvipc=true\n\nRUN pkg install -y postgresql18-server\n\nSERVICE postgresql --no-user\n\nRUN service postgresql oneinitdb\n\nCOPY postgresql.conf /var/db/postgres/data18/postgresql.conf\nCOPY pg_hba.conf /var/db/postgres/data18/pg_hba.conf\n\nEXPOSE 5432\n```\n\n```bash\n# Build and run\ndoas dail run postgres.dail --preset postgres\n\n# Check status\ndoas dail ls\n\n# View logs\ndoas dail logs postgresql\n\n# Create a user and database for your app (e.g. \"zid\")\ndoas -u postgres createuser --pwprompt zid -h 10.100.0.2\ndoas -u postgres createdb -O zid zid -h 10.100.0.2\n\n# Connect from host\npsql -h 10.100.0.2 -U zid -d zid\n\n# Open shell inside jail\ndoas dail shell postgresql\n\n# Stop and remove\ndoas dail stop postgresql\ndoas dail rm postgresql\n```\n\n### Custom Rust service (filest)\n\n```dockerfile\n# filest.dail\nFROM 15.0-RELEASE\n\nSERVICE filest\n\nCOPY target/release/filest /usr/local/bin/filest\n\nEXPOSE 8090\n```\n\n```bash\n# Build the binary on host first\ncargo build --release\n\n# Build jail and run\n# --uid makes mount ownership match host user\n# -e passes namespace config to the service\ndoas dail run filest.dail --uid 1001 \\\n  --mount /home/user/photos:/data/photos \\\n  -e NS_photos=/data/photos\n\n# Check it's running\ndoas dail ls\ncurl http://10.100.0.2:8090/\n\n# View logs\ndoas dail logs filest\n\n# Rebuild after code changes\ncargo build --release\ndoas dail run filest.dail --rebuild\n\n# Stop\ndoas dail stop filest\n```\n\n## `.dail` File Reference\n\nA `.dail` file describes how to build and run a jail — similar to a Dockerfile.\n\n```dockerfile\n# Base FreeBSD release\nFROM 15.0-RELEASE\n\n# Install packages\nRUN pkg install -y nginx\n\n# Copy config files from build context into the jail\nCOPY nginx.conf /usr/local/etc/nginx/nginx.conf\n\n# Set environment variables (appended to /etc/profile)\nENV APP_ENV=production\n\n# Jail parameters (FreeBSD jail.conf options)\nPARAM allow.raw_sockets=true\n\n# Mount host directories into the jail\nMOUNT /home/user/site:/usr/local/www\nMOUNT /data:/mnt/data:ro\n\n# Enable a service (creates user/group/dirs, adds to rc.conf)\nSERVICE nginx --no-user\n\n# Log file path (used by `dail logs`)\nLOG /var/log/nginx/access.log\n\n# Port forwarding (host_port:jail_port)\nEXPOSE 8080:80\nEXPOSE 443\n\n# Override default startup command\nCMD /usr/local/sbin/nginx -g \"daemon off;\"\n```\n\n| Directive | Syntax | Description |\n|-----------|--------|-------------|\n| `FROM` | `FROM \u003crelease\u003e` | FreeBSD base release |\n| `RUN` | `RUN \u003ccommand\u003e` | Execute command during build |\n| `COPY` | `COPY [--chown=u:g] \u003csrc\u003e \u003cdst\u003e` | Copy files into jail (supports globs). Auto-chown to SERVICE user if present |\n| `ENV` | `ENV \u003cKEY\u003e=\u003cVALUE\u003e` | Set environment variable |\n| `PARAM` | `PARAM \u003ckey\u003e=\u003cvalue\u003e` | Set jail parameter (see [jail(8)](https://man.freebsd.org/cgi/man.cgi?jail(8))) |\n| `MOUNT` | `MOUNT \u003csrc\u003e:\u003cdst\u003e[:ro]` | Mount host directory (optional `:ro` suffix) |\n| `SERVICE` | `SERVICE \u003cname\u003e [--no-user]` | Enable service, create user/group/dirs, set persist |\n| `LOG` | `LOG \u003cpath\u003e` | Log file for `dail logs` |\n| `EXPOSE` | `EXPOSE [host:]\u003cport\u003e[/proto]` | Port forwarding (default tcp, overridden by `-p`) |\n| `CMD` | `CMD \u003ccommand\u003e` | Startup command (overrides SERVICE default) |\n\n### Common PARAM values\n\n| Parameter | Description |\n|-----------|-------------|\n| `allow.raw_sockets=true` | Allow ping and raw socket access |\n| `allow.sysvipc=true` | Allow SysV IPC (required by PostgreSQL) |\n| `allow.mlock=true` | Allow memory locking |\n| `allow.chflags=true` | Allow changing file flags |\n| `ip4=inherit` | Share host IPv4 stack |\n| `ip6=inherit` | Share host IPv6 stack |\n| `children.max=5` | Allow nested jails (up to N) |\n| `securelevel=0` | Set jail securelevel |\n\nFull list: [jail(8)](https://man.freebsd.org/cgi/man.cgi?jail(8))\n\n## Commands\n\n### Setup\n\n**`dail config init`** — Initialize dail: create directory structure (`/var/db/dail/`), write default config.\n\n```bash\ndail config init                    # directory backend\ndail config init --zfs-pool zroot   # ZFS backend\n```\n\n**`dail bootstrap`** — Download and extract a FreeBSD base system.\n\n```bash\ndail bootstrap                      # download default (15.0-RELEASE)\ndail bootstrap 14.2-RELEASE         # specific release\ndail bootstrap --list               # show bootstrapped bases\n```\n\n### Jail Lifecycle\n\n**`dail create`** — Create a jail without starting it.\n\n```bash\ndail create myjail                                          # thick jail, default base\ndail create myjail --type thin --base 14.2-RELEASE\ndail create myjail --preset postgres                        # apply preset\ndail create web --vnet --vnet-ip 10.0.0.5/24 --vnet-gateway 10.0.0.1\ndail create app --mount /data/app:/app --allow raw_sockets --limit maxproc=256\ndail create web -p 8080:80                                  # port forwarding via PF\ndail create app --uid 1001                                   # service user with specific UID/GID\n```\n\n**`dail run`** — Create and start a jail in one step. Same options as `create`, plus `--rm`, `--build`, `--rebuild`.\n\n```bash\ndail run myjail                                             # create + start\ndail run postgres-jail --preset postgres                    # with preset\ndail run temp --rm                                          # auto-remove on stop\ndail run web --vnet --vnet-ip 10.0.0.5/24 --vnet-gateway 10.0.0.1\ndail run app --mount /data:/app --preset dev --limit maxproc=512\ndail run postgres.dail                                      # build + start, name from filename\ndail run postgres.dail --name pg                            # build with explicit name\ndail run postgres.dail --rebuild                            # rebuild from scratch\ndail run https://github.com/user/repo.git --name app        # build from git repo\ndail run https://github.com/user/repo//jails/web --name web # build from subdirectory\ndail run web -p 8080:80                                     # port forwarding\ndail run web -p 8080:80/tcp -p 5432:5432                    # multiple ports\ndail run app.dail --uid 1001                                 # service user with specific UID/GID\n```\n\n**`dail start`** / **`stop`** / **`restart`** — Manage jail state.\n\n```bash\ndail start myjail\ndail stop myjail                    # if --rm was set, jail is auto-removed\ndail stop --all                     # stop all running jails\ndail restart myjail\ndail restart --all                  # restart all running jails\n```\n\n**`dail rm`** — Remove a jail and its filesystem.\n\n```bash\ndail rm myjail                      # must be stopped\ndail rm myjail --force              # stop + remove\ndail rm --all --force               # remove all jails\n```\n\n### Inspection\n\n**`dail ls`** — List jails.\n\n```bash\ndail ls                             # all jails (colored status)\ndail ls --running                   # only running\ndail ls --format json               # JSON output\ndail ls -q                          # names only (for scripting)\n```\n\n**`dail inspect`** — Show jail details.\n\n```bash\ndail inspect myjail                 # human-readable\ndail inspect myjail --json          # raw JSON\n```\n\n**`dail config show`** — Display current configuration.\n\n```bash\ndail config show\n```\n\n### Execution\n\n**`dail exec`** — Run a command inside a jail.\n\n```bash\ndail exec myjail ls /etc\ndail exec myjail pkg install -y nginx\n```\n\n**`dail shell`** — Open an interactive shell.\n\n```bash\ndail shell myjail                 # default /bin/sh\ndail shell myjail --shell /bin/csh\n```\n\n### Logs\n\n**`dail logs`** — View jail logs. By default reads CMD stdout/stderr (`cmd.log`). If `LOG` is set in the `.dail` file, reads that file from the jail rootfs instead. The log file is auto-created with write permissions at jail start.\n\n```bash\ndail logs myjail                        # CMD output (or LOG file if set in .dail)\ndail logs myjail --tail 20              # last 20 lines\ndail logs myjail -f                     # follow (like tail -f)\ndail logs myjail --file /var/log/messages  # read arbitrary file from jail rootfs\n```\n\n### Monitoring\n\n**`dail top`** — Show running processes inside a jail.\n\n```bash\ndail top myjail                     # watch mode (refreshes every 2s)\ndail top myjail --once              # single snapshot\n```\n\n### Build\n\n**`dail build`** — Build a jail from a `.dail` file or git URL.\n\n```bash\ndail build pg.dail --name myapp\ndail build ./jails/web.dail --name web\ndail build https://github.com/user/repo.git --name app                  # build from git repo\ndail build https://github.com/user/repo//jails/web --name web           # build from subdirectory\n```\n\n### Cache\n\n**`dail cache clean`** — Remove cached pkg packages and repository metadata.\n\n```bash\ndail cache clean\n```\n\n### Shell Completions\n\nDail supports dynamic completions — jail names and other values are completed at runtime.\n\n```bash\n# Dynamic completions (recommended — live jail name and image completion)\necho 'source \u003c(COMPLETE=zsh dail)' \u003e\u003e ~/.zshrc\necho 'source \u003c(COMPLETE=bash dail)' \u003e\u003e ~/.bashrc\nCOMPLETE=fish dail \u003e ~/.config/fish/completions/dail.fish\n\n# Static completions (subcommands and flags only, no live names)\ndail completions zsh | doas tee /usr/local/share/zsh/site-functions/_dail \u003e /dev/null\ndail completions bash | doas tee /usr/local/etc/bash_completion.d/dail \u003e /dev/null\ndail completions fish \u003e ~/.config/fish/completions/dail.fish\n```\n\n### Snapshots\n\n**`dail snapshot`** — Create a ZFS snapshot (requires ZFS backend).\n\n```bash\ndail snapshot myjail                # tag: latest\ndail snapshot myjail --tag v1.0\n```\n\n**`dail clone`** — Clone a jail from a snapshot.\n\n```bash\ndail clone myjail myjail-copy              # from latest\ndail clone myjail:v1.0 myjail-copy         # from tagged snapshot\n```\n\n### Presets\n\n**`dail preset`** — List available presets.\n\n```bash\ndail preset\n```\n\n## Presets\n\nPresets apply common jail parameters in one flag:\n\n| Preset | What it does |\n|--------|-------------|\n| `postgres` | `allow.sysvipc=true` |\n| `dev` | `allow.raw_sockets=true`, `allow.sysvipc=true` |\n\nCustom presets: create YAML (or TOML) files in `/var/db/dail/presets/`:\n\n```yaml\n# /var/db/dail/presets/myapp.yaml\ndescription: \"My custom app\"\nparams:\n  allow.raw_sockets: \"true\"\nlimits:\n  maxproc: \"256\"\n```\n\n## Network Modes\n\nDail supports multiple networking configurations:\n\n### Auto IP Allocation (default)\n\nWhen no network flags are specified, dail automatically allocates an IP from the configured pool:\n\n```bash\ndail run myjail                      # Auto-allocates 10.100.0.X\n# Output: IP allocated: 10.100.0.2 on lo0\n```\n\nPool configured in `/usr/local/etc/dail/config.yaml`:\n\n```yaml\nip_pool: 10.100.0.0/24\nalias_interface: lo0\n```\n\n### Explicit IP Alias\n\nAssign a specific IP address:\n\n```bash\ndail create web --ip 10.100.0.50/24\n```\n\n**Note:** Dail validates that the IP is not already in use by another jail.\n\n### VNET (Virtual Network)\n\nFull network stack isolation with bridged networking:\n\n```bash\ndail create app --vnet --vnet-ip 10.0.0.5/24 --vnet-gateway 10.0.0.1 --vnet-bridge bridge0\n```\n\n### Port Forwarding\n\nForward host ports to jail ports using PF rdr anchors:\n\n```bash\ndail run web -p 8080:80                    # forward host:8080 → jail:80\ndail run web -p 8080:80/tcp -p 5432:5432   # multiple ports, optional proto\n```\n\nRequires PF enabled with the dail anchor in `/etc/pf.conf`:\n\n```\nrdr-anchor \"dail/*\"\n```\n\nIn `.dail` files, use `EXPOSE` to declare default port mappings:\n\n```dockerfile\nEXPOSE 5432\nEXPOSE 8080:80\n```\n\nIf `-p` is passed on the CLI, all `EXPOSE` directives are ignored.\n\n### Host Network (inherit)\n\nShare the host's network stack:\n\n```bash\ndail create legacy --network inherit\n```\n\n### No Network (isolated)\n\nCompletely isolated jail with no network access:\n\n```bash\ndail create isolated --network none\n```\n\n## Configuration\n\nGlobal config at `/usr/local/etc/dail/config.yaml` (TOML fallback supported):\n\n```yaml\nroot_dir: /var/db/dail\nstorage_backend: directory  # or \"zfs\"\ndefault_base: \"15.0-RELEASE\"\nalias_interface: lo0\nip_pool: 10.100.0.0/24\nmirror: https://download.freebsd.org/releases\n\n# Optional: for ZFS backend\n# zfs_pool: zroot\n```\n\n## Requirements\n\n- FreeBSD 13+\n- Rust (for building from source)\n- ZFS (optional, for snapshot/clone features)\n\n## Building\n\n```bash\ncargo build --release\n```\n\n## License\n\nBSD-3-Clause\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeslava%2Fdail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzeslava%2Fdail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeslava%2Fdail/lists"}