{"id":44449051,"url":"https://github.com/studiometa/trafic","last_synced_at":"2026-03-04T19:02:45.391Z","repository":{"id":337487957,"uuid":"848257173","full_name":"studiometa/trafic","owner":"studiometa","description":"🚦 Configure your server as a DDEV staging server with access control and scale-to-zero features","archived":false,"fork":false,"pushed_at":"2026-02-12T15:28:08.000Z","size":396,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-02-12T22:55:42.118Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/studiometa.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-08-27T12:35:57.000Z","updated_at":"2026-02-12T15:34:35.000Z","dependencies_parsed_at":"2026-02-09T23:01:42.779Z","dependency_job_id":null,"html_url":"https://github.com/studiometa/trafic","commit_stats":null,"previous_names":["studiometa/trafic"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/studiometa/trafic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/studiometa%2Ftrafic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/studiometa%2Ftrafic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/studiometa%2Ftrafic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/studiometa%2Ftrafic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/studiometa","download_url":"https://codeload.github.com/studiometa/trafic/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/studiometa%2Ftrafic/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30086079,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T15:40:14.053Z","status":"ssl_error","status_checked_at":"2026-03-04T15:40:13.655Z","response_time":59,"last_error":"SSL_read: 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":[],"created_at":"2026-02-12T16:10:02.626Z","updated_at":"2026-03-04T19:02:45.214Z","avatar_url":"https://github.com/studiometa.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🚦 Trafic\n\n[![NPM Version](https://img.shields.io/npm/v/@studiometa/trafic-cli.svg?style=flat\u0026colorB=3e63dd\u0026colorA=414853)](https://www.npmjs.com/package/@studiometa/trafic-cli/)\n[![Downloads](https://img.shields.io/npm/dm/@studiometa/trafic-cli?style=flat\u0026colorB=3e63dd\u0026colorA=414853)](https://www.npmjs.com/package/@studiometa/trafic-cli/)\n![Codecov](https://img.shields.io/codecov/c/github/studiometa/trafic?style=flat\u0026colorB=3e63dd\u0026colorA=414853)\n\n**DDEV preview environments on any Linux server.**\n\nTrafic turns a VPS into a preview server for your web projects. It handles authentication, scale-to-zero, auto-start, and deployments from CI — all powered by [DDEV](https://ddev.com) and [Traefik](https://traefik.io).\n\n## Features\n\n- **DDEV-native** — No custom Dockerfiles needed. Works with WordPress, Laravel, Drupal, and any DDEV-compatible project.\n- **Scale-to-zero** — Idle projects are stopped automatically to save RAM. They restart on the next request.\n- **Authentication** — Forward auth via Traefik with IP whitelist, tokens, basic auth, and per-hostname rules.\n- **Preview environments** — Create and destroy environments from CI, like Vercel but for PHP.\n- **Simple CLI** — `setup` (server), `deploy` (CI), `destroy` (cleanup).\n- **TOML config** — Simple, readable configuration.\n- **Zero vendor lock-in** — Runs on any Linux VPS with SSH access.\n\n## How it works\n\n```mermaid\nflowchart TD\n  request[HTTPS request] --\u003e traefik[Traefik / DDEV router]\n  traefik --\u003e forwardAuth[forwardAuth → trafic agent]\n  forwardAuth --\u003e |200 OK| ddev-web[DDEV project]\n  forwardAuth --\u003e |401| basic-auth[Basic auth prompt]\n  traefik --\u003e |502 error| errors[errors middleware → trafic agent]\n  errors --\u003e |known project| waiting[Waiting page + auto-start]\n  errors --\u003e |unknown project| error-page[Error page]\n```\n\n## Quick start\n\n```bash\n# Setup a server (run on the server as root)\nnpx @studiometa/trafic-agent setup --tld=previews.example.com --email=admin@example.com\n\n# Deploy from CI\nnpx @studiometa/trafic-cli deploy \\\n  --host=server.example.com \\\n  --name=my-app \\\n  --branch=main \\\n  --sync=\"dist/\" \\\n  --script=\"composer install --no-dev\"\n\n# Your app is live at https://my-app.previews.example.com\n```\n\n## Packages\n\n| Package | Description | npm |\n| ------- | ----------- | --- |\n| [`@studiometa/trafic-cli`](packages/trafic-cli/) | CLI for deploying projects from CI | [![NPM Version](https://img.shields.io/npm/v/@studiometa/trafic-cli?style=flat\u0026colorB=3e63dd\u0026colorA=414853)](https://www.npmjs.com/package/@studiometa/trafic-cli/) |\n| [`@studiometa/trafic-agent`](packages/trafic-agent/) | Server agent (auth, scale-to-zero) | [![NPM Version](https://img.shields.io/npm/v/@studiometa/trafic-agent?style=flat\u0026colorB=3e63dd\u0026colorA=414853)](https://www.npmjs.com/package/@studiometa/trafic-agent/) |\n\n## Requirements\n\n**Server:**\n- Ubuntu 24.04 LTS\n- Root access (for initial setup)\n- Wildcard DNS (`*.previews.example.com` → server IP)\n\n**CI:**\n- Node.js 24+\n- SSH access to the server\n\n## CI examples\n\n\u003cdetails\u003e\n\u003csummary\u003eGitLab CI\u003c/summary\u003e\n\n```yaml\ndeploy_preview:\n  stage: deploy\n  image: node:24\n  before_script:\n    - eval $(ssh-agent -s)\n    - chmod 600 \"$SSH_PRIVATE_KEY\"\n    - ssh-add \"$SSH_PRIVATE_KEY\"\n  script:\n    - npx @studiometa/trafic-cli deploy\n        --host $SSH_HOST\n        --name $CI_PROJECT_PATH_SLUG\n        --preview $CI_MERGE_REQUEST_IID\n        --sync \"dist/\"\n        --script \"composer install --no-dev\"\n  rules:\n    - if: $CI_MERGE_REQUEST_ID\n\ndestroy_preview:\n  stage: deploy\n  image: node:24\n  when: manual\n  before_script:\n    - eval $(ssh-agent -s)\n    - chmod 600 \"$SSH_PRIVATE_KEY\"\n    - ssh-add \"$SSH_PRIVATE_KEY\"\n  script:\n    - npx @studiometa/trafic-cli destroy\n        --host $SSH_HOST\n        --name $CI_PROJECT_PATH_SLUG\n        --preview $CI_MERGE_REQUEST_IID\n  rules:\n    - if: $CI_MERGE_REQUEST_ID\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGitHub Actions\u003c/summary\u003e\n\n```yaml\ndeploy_preview:\n  runs-on: ubuntu-latest\n  if: github.event_name == 'pull_request'\n  steps:\n    - uses: actions/checkout@v4\n    - uses: webfactory/ssh-agent@v0.9.0\n      with:\n        ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}\n    - run: npx @studiometa/trafic-cli deploy\n        --host ${{ vars.SSH_HOST }}\n        --name ${{ github.event.repository.name }}\n        --preview ${{ github.event.pull_request.number }}\n        --sync \"dist/\"\n        --script \"composer install --no-dev\"\n\ndestroy_preview:\n  runs-on: ubuntu-latest\n  if: github.event_name == 'pull_request' \u0026\u0026 github.event.action == 'closed'\n  steps:\n    - uses: webfactory/ssh-agent@v0.9.0\n      with:\n        ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}\n    - run: npx @studiometa/trafic-cli destroy\n        --host ${{ vars.SSH_HOST }}\n        --name ${{ github.event.repository.name }}\n        --preview ${{ github.event.pull_request.number }}\n```\n\n\u003c/details\u003e\n\n## Documentation\n\n- [CLI README](packages/trafic-cli/README.md) — Deploy and destroy commands\n- [Agent README](packages/trafic-agent/README.md) — Server setup and configuration\n- [Example config](examples/config.toml) — Full configuration reference\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.\n\n## Security\n\nSee [SECURITY.md](SECURITY.md) for reporting vulnerabilities.\n\n## License\n\n[MIT](LICENSE) © [Studio Meta](https://www.studiometa.fr/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstudiometa%2Ftrafic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstudiometa%2Ftrafic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstudiometa%2Ftrafic/lists"}