NextDeploy Documentation
Star on GitHub1NextDeploy is a self-hosted deployment engine for Next.js. It builds a complete picture of your app at build time — routes, integrations, secrets, assets — and uses that intelligence to deploy correctly to your own VPS or AWS, without a platform in the middle.
No monthly platform bill. No vendor lock-in. Your infrastructure, your AWS account, your server.
Early Access — v0.1.x
Works well for personal and small-team projects. APIs may change between minor versions. Back up secrets and read changelogs before upgrading. Use nextdeploy update to get the latest binary.
How it actually works
Most deployment tools are transport layers — they move your build from A to B. NextDeploy is different. Every nextdeploy build produces a metadata.json that statically analyses your Next.js output before a single file is uploaded:
Route classification
Separates static, SSR, ISR, API, and middleware routes by parsing Next.js manifests. No config needed.
Integration detection
Detects Stripe, Cloudinary, Google Analytics, YouTube, and other external origins from the build output — not source code.
ISR awareness
Identifies ISR routes and revalidation intervals. Foundation for selective CDN invalidation instead of nuking the whole cache.
Secret cross-referencing
Knows which integrations your app uses. Can warn before deploy if Stripe is detected but STRIPE_KEY is missing.
Git provenance
Records commit hash and dirty state at build time. Every deploy is traceable. Warns if you're shipping uncommitted changes.
Security Sandboxing
Configures DynamicUser, ProtectSystem=strict, and PrivateTmp for process isolation. Minimal attack surface.
WAF & HMAC
Integrated Coraza WAF (OWASP CRS) and HMAC-SHA256 request signing between CLI and daemon.
Build fingerprint
Knows your package manager, entrypoint, output mode, Next.js version, and full asset inventory. Deploys exactly what your app needs.
This intelligence layer is what separates NextDeploy from a glorified deploy script. The metadata drives pre-deploy validation, targeted cache invalidation, deployment provenance, and — on the roadmap — per-route CloudFront behavior configuration that eliminates unnecessary Lambda invocations entirely.
What it handles today
- ✓VPS deployments — atomic port-swap, zero-downtime, Caddy reverse proxy, Fail2Ban, HSTS
- ✓Advanced isolation — DynamicUser, ProtectSystem=strict, PrivateTmp, and NoNewPrivileges
- ✓AWS serverless — Lambda + S3 + CloudFront + ACM, fully provisioned on first deploy
- ✓Build intelligence — static analysis of every Next.js build, route classification, integration detection
- ✓Lambda bridge adapter — translates Lambda events to HTTP for the Next.js standalone server
- ✓Secret management — encrypted locally, pushed to AWS Secrets Manager, injected via Lambda Extension at cold-start
- ✓Audit logging — structured JSON logs of every command and system change for traceability
- ✓Rollbacks — VPS ring buffer keeps last 5 releases, serverless restores from S3 deployment history
- ✓Deployment provenance — git commit, dirty state, Next.js version, and build timestamp on every deploy
- ✓Self-updating CLI — single static binary, no runtime dependencies, updates via GitHub Releases
Current limitations worth knowing
- • Lambda size limit: 250MB unzipped. Apps with heavy native binaries (sharp, Prisma) may exceed this.
- • No edge runtime: Next.js middleware runs at the edge. Everything currently routes to a single Lambda origin.
- • Single region: One Lambda per deploy. Multi-region requires manual configuration.
- • No ISR cache layer yet: ISR routes are detected and classified but selective revalidation isn't wired up yet — it's on the roadmap.
- • AWS only (for now): Cloudflare, GCP, and Azure providers are planned. The provider interface is already built for it.
Installation
CLI (your machine)
A single static binary. No Node, no runtime dependencies.
curl -sSf https://nextdeploy.org/install.sh | shDaemon (VPS only)
Runs as a systemd service on your server. Handles health checks, atomic swaps, release management, and secret injection via a Unix socket control plane. Not needed for serverless.
curl -sSf https://nextdeploy.org/daemon.sh | shVPS Deployment
Deploy to any Linux server you own or rent.
1. Initialize
nextdeploy initCreates nextdeploy.yml in your project root with sensible defaults.
2. Configure
version: "1.0"
target_type: vps
app:
name: my-next-app
domain: app.example.com
port: 3000
environment: production
servers:
- name: prod
host: 1.2.3.4
port: 22
username: deploy
ssh_key: ~/.ssh/id_rsa3. Prepare the server (once)
Runs an Ansible playbook that installs Node, Bun, Caddy, Fail2Ban, and the NextDeploy daemon. Configures systemd with advanced isolation (DynamicUser=yes, ProtectSystem=strict), Unix socket permissions, and Caddy HTTPS automatically.
nextdeploy prepare4. Deploy
nextdeploy shipship runs the full pipeline in one step — analyses your Next.js output, produces the metadata and artifact, uploads via SFTP, and signals the daemon for an atomic port-swap that's health checked before traffic cuts over. Incremental: skips the rebuild step when nothing has changed.
For CI pipelines that want a separate build stage, run nextdeploy build first — it produces the same artifact ship would have built. Add --force to either command to bypass the incremental cache.
Rollback
The daemon keeps your last 5 releases. Revert instantly:
nextdeploy rollbackServerless Deployment (AWS)
No servers, no daemon — Lambda + S3 + CloudFront, provisioned automatically.
What gets provisioned on first deploy
- • S3 bucket with correct MIME types and cache headers per asset type
- • Lambda function + IAM execution role
- • Lambda Function URL with CloudFront OAC — Lambda is never publicly exposed
- • ACM certificate for your custom domain
- • CloudFront distribution wired to both S3 and Lambda
- • AWS Secrets Manager namespace for your app
Prerequisite: AWS credentials in ~/.aws/credentials with the permissions listed in the AWS Deployer Permissions section.
1. Configure
version: "1.0"
target_type: serverless
app:
name: my-next-app
domain: app.example.com
serverless:
provider: aws
region: us-east-1 # ACM certificates must be us-east-1 for CloudFrontTutorial: Automated AWS Serverless Deployment
2. Add output: 'standalone'
// next.config.mjs
const nextConfig = {
output: 'standalone',
}
export default nextConfigWhy standalone?
Default Next.js builds include the full node_modules — often 500MB+, over Lambda's 250MB unzipped limit. Standalone mode traces your actual imports and produces a self-contained server.js. NextDeploy then injects a bridge adapter that translates Lambda invocation events into HTTP requests the Next.js server understands.
3. Deploy
nextdeploy shipOne command runs the full pipeline. ship builds your app (only when something changed), then:
Validate build
Reads metadata.json — route types, integrations, ISR config, git state. Validates before uploading anything.
Push secrets
Syncs secrets to AWS Secrets Manager. They never touch the artifact or Lambda env vars directly.
Upload static assets
Syncs public/ and _next/static/ to S3 with correct MIME types and cache headers per asset type.
Deploy Lambda
Injects bridge adapter, zips .next/standalone/, updates Lambda via UpdateFunctionCode with retry logic for IAM propagation.
SSL + DNS guide
ACM cert requested. Detailed DNS guide generated in report. Re-run ship after DNS propagates.
Bust CDN cache
CloudFront /* invalidation triggered. Selective per-route invalidation using ISR metadata is on the roadmap.
Secret Management
Encrypted locally. Never in build artifacts. Never hardcoded in Lambda env vars.
Commands from the CLI are now cryptographically signed using HMAC-SHA256 to ensure daemon control plane integrity.
nextdeploy secrets set DATABASE_URL "postgres://user:pass@host/db"
nextdeploy secrets load
nextdeploy secrets list
nextdeploy secrets delete OLD_KEYHow secrets are stored
- VPSEncrypted on-disk at
/opt/nextdeploy/secrets/with 0600 permissions. Decrypted and injected as environment variables at startup. Key is derived per-machine. - AWSPushed to AWS Secrets Manager under
nextdeploy/apps/<name>/production. Lambda fetches them at cold-start via the AWS Secrets Extension — available as plainprocess.env. Only the ARN is set in Lambda, not the values.
DNS Configuration
How to point your domain to your new infrastructure correctly.
The "Loud" DNS Guide
NextDeploy generates a dns.md file in your project root and a visual DNS Setup Guide in your deployment report. It explicitly tells you which records to add to your registrar.
VPS Target
Point your domain directly to your server IP.
- • A Record:
@→Server IP - • CNAME:
www→@
Caddy handles SSL automatically via Let's Encrypt once DNS propagates.
Serverless Target
Requires two steps: verify ownership and route traffic.
- 1. SSL Validation (ACM)Add the unique CNAME records provided in your report to prove ownership to AWS.
- 2. Traffic RoutingPoint your domain to the CloudFront distribution:
@→xxxx.cloudfront.net
Security & Isolation
Hardened by default for both VPS and Serverless deployments.
HMAC-SHA256 Command Signing
All CLI-to-Daemon commands require a cryptographic signature. A shared secret is generated during 'nextdeploy prepare', ensuring only authorized clients can control your apps.
Coraza WAF Integration
Caddy includes an embedded Web Application Firewall using the OWASP Core Rule Set. It blocks SQLi, XSS, and common exploit attempts at the edge.
Advanced Systemd Sandboxing
Apps run with DynamicUser=yes, ProtectSystem=strict, and PrivateTmp=yes. The process is sandboxed with minimal kernel attack surface and no filesystem access outside its data dir.
Structured Audit Logging
Every deployment, secret change, and system command is recorded in JSON format at /var/log/nextdeployd/audit.log for full environment traceability.
Mutual TLS (mTLS)
Daemon communication supports an optional TCP+mTLS listener. For network-attached management, both client and server must present valid certificates.
Atomic Permissions
Unix sockets are restricted to the 'nextdeploy' group with 0660 permissions, ensuring local privilege separation between users and the deployment plane.
Deep Dive: NextCore Metadata
The "Brain" that makes NextDeploy provider-agnostic.
During nextdeploy build, the NextCore engine performs a deep inspection of your Next.js build output. It doesn't just copy files; it understands the intent of every route and asset.
Metadata Analysis Loop
The resulting metadata.json serves as the source of truth for all providers:
VPS (nextdeployd)
- • Maps the entrypoint to a Systemd Sandbox
- • Allocates and persists Dynamic Ports
- • Translates Domain metadata to Caddyfile Directives
AWS Serverless
- • Splits assets between S3 (Static) and Lambda (Dynamic)
- • Configures CloudFront Behaviors per route type
- • Maps secrets to AWS Secrets Manager
CLI Reference
nextdeploy initScaffold nextdeploy.yml in your projectnextdeploy shipBuild (incrementally) and deploy in one step — the typical command. Targets VPS or serverless based on nextdeploy.yml.nextdeploy ship --forceForce a full rebuild before deploying (skips the incremental cache).nextdeploy buildRun only the build stage — analyse Next.js output, classify routes, detect integrations, produce metadata.json and app.tar.gz. Useful for CI when you want build and deploy on separate runners.nextdeploy build --forceForce a clean rebuild from scratch.nextdeploy prepareProvision a VPS — Caddy, daemon, Fail2Ban, Node, Bun, systemd (VPS only)nextdeploy rollbackRevert to the previous release (VPS ring buffer or S3 history)nextdeploy statusShow health, active release, route summary, and resource usagenextdeploy logsTail live application logs from the servernextdeploy secrets loadLoad secrets from a .env file to your server securelynextdeploy secrets set KEY VALUEEncrypt and store — routed to daemon store or AWS Secrets Manager automaticallynextdeploy secrets listList secret names (values always hidden)nextdeploy secrets delete KEYRemove a secret permanentlynextdeploy updateSelf-update the CLI binary from GitHub ReleasesConfiguration reference
version: "1.0"
target_type: vps
app:
name: my-next-app # Used for process naming and secret namespacing
domain: app.example.com # Caddy configures HTTPS automatically
port: 3000
environment: production
servers:
- name: prod
host: 1.2.3.4
port: 22
username: deploy
ssh_key: ~/.ssh/id_rsa
secrets:
provider: local # "local" | "doppler" coming soon
logging:
enabled: trueArchitecture
VPS
Serverless
Under the hood
CLI
- • Next.js manifest parsing + route classification
- • Static integration detection from build output
- • HMAC-SHA256 request signing & verification
- • Build metadata generation per deploy
- • Encrypted local secret storage
- • SFTP (VPS) or AWS SDK (serverless)
- • Self-update via GitHub Releases
Daemon (VPS)
- • Systemd with socket & process isolation
- • DynamicUser & ProtectSystem sandboxing
- • Unix socket & TCP/mTLS control plane
- • Health check + port arbitration & persistence
- • Atomic hot-swap with instant rollback
- • Release buffer (last 5 builds)
- • Secret hot-reload without restart
Serverless engine
- • Lambda bridge adapter (event → HTTP)
- • CloudFront OAC + Lambda URL auth
- • S3 deployment history for rollback
- • Lambda version publishing per deploy
- • Idempotent AWS resource provisioning
- • Provider interface (GCP, Cloudflare planned)
Roadmap
The build metadata layer already collects the data needed for most of these. Several are one function away from the information that enables them.