{"title":"Deployment","description":"Build and run an Amber V2 web application without relying on obsolete platform buildpacks","section":"","version":"v2","path":"deployment","canonical_url":"https://amberframework.org/docs/v2/deployment","markdown_url":"https://amberframework.org/docs/v2/deployment.md","inherited":false,"content_markdown":"# Deployment\n\nDeploy Amber V2 as a compiled Crystal executable. The beta does not publish a\nverified one-click recipe for Heroku, Dokku, DigitalOcean, or another hosting\nvendor. Those V1 pages depended on old Crystal versions, Webpack or Node asset\nbuilds, bundled database commands, Redis defaults, and retired buildpacks, so\nthey are not carried into V2.\n\nThe portable deployment contract is:\n\n1. install production shard dependencies;\n2. build and verify application-authored assets;\n3. run the test suite;\n4. compile the application target in release mode;\n5. package the binary, configuration, and public files as one release;\n6. provide production configuration through environment variables; and\n7. run the binary behind a TLS-terminating reverse proxy or managed ingress.\n\n```bash\nshards install --production\namber assets build\namber assets check\ncrystal spec\nshards build my_app --release\n```\n\nAn existing application without a compatible standalone CLI can run\n`crystal run scripts/build_assets.cr` and its verification wrapper as documented\nin [Asset Pipeline](../guides/assets/). Never start the web process to generate\nassets and never rely on a first request to populate `public/`.\n\nThe generated target writes `bin/my_app`. Build on the same operating-system\nand CPU family used by the runtime unless you have deliberately configured a\ncross-compilation toolchain.\n\n## Asset release artifact\n\nA manifest-enabled release contains, at minimum:\n\n```text\nbin/my_app\nconfig/\npublic/robots.txt\npublic/assets/manifest.json\npublic/assets/...fingerprinted files...\n```\n\nThe compiler also writes deterministic `.gz` companions for compressible\nfiles. A compatible Amber static handler can select them for clients accepting\ngzip while preserving the original content type and `Vary: Accept-Encoding`.\nIf a reverse proxy handles compression instead, test that the two layers do not\nproduce conflicting encodings.\n\nDeploy the entire release to a new directory and verify it before shifting\ntraffic. Fingerprinted URLs can use\n`Cache-Control: public, max-age=31536000, immutable`; HTML, the manifest, and\nunfingerprinted paths must revalidate. Keep the prior complete release available\nfor rollback while its HTML may still be cached.\n\n**File: `config/environments/production.yml` — use the typed top-level static\nsection for the fallback policy on unfingerprinted files.**\n\n```yaml\nstatic:\n  headers:\n    Cache-Control: \"no-cache\"\n```\n\nDo not put this under the legacy `pipes:` shape in a V2 configuration file.\nAmber's static handler overrides the fallback with one-year immutable caching\nwhen the requested filename contains a content fingerprint.\n\nRuntime uploads are not in this artifact. Put them on a persistent mounted\nvolume or in object storage, with independent backup and access controls. Never\nrun user-controlled files through the authored-asset compiler.\n\n## Required runtime configuration\n\n```bash\nexport AMBER_ENV=production\nexport AMBER_SERVER_HOST=0.0.0.0\nexport AMBER_SERVER_PORT=3000\nexport AMBER_SERVER_SECRET_KEY_BASE=\"replace-with-a-long-random-secret\"\n./bin/my_app\n```\n\nSet `DATABASE_URL` to the production database selected by the application. The\ndefault V2 web template includes Grant and SQLite; PostgreSQL and MySQL apps\ninclude their selected driver instead. Never commit the production secret or\ndatabase credentials or inject them into a container image.\n\nRun migrations as an explicit release step before starting code that requires\nthe new schema:\n\n```bash\nAMBER_ENV=production DATABASE_URL=\"...\" amber database migrate\n```\n\n## Platform checklist\n\n- Route external HTTPS traffic through a reverse proxy or managed ingress.\n- Forward to the port in `AMBER_SERVER_PORT`; do not run the process as root to\n  bind directly to ports 80 or 443.\n- Preserve termination signals so the process can shut down cleanly.\n- Capture standard output and standard error with the platform log service.\n- Restart failed processes with the platform supervisor.\n- Back up and prove restore before applying production migrations.\n- Start the application with the release directory read-only; only explicit\n  runtime-data locations should be writable.\n- Request one fingerprinted CSS, JavaScript, image, font, and binary URL and\n  verify its bytes, MIME type, compression, and cache headers before shifting\n  traffic.\n\nContinue with [Manual binary deployment](manual-deploy/) for a concrete Linux\nservice example."}