@pxilab/nextship
v0.3.1
Published
Next.js deployment tool - Build, SSH upload, PM2 restart
Maintainers
Readme
PXI NextShip
Next.js deployment tool - Build, SSH upload, PM2 restart.
Installation
# npm
npm install -g @pxilab/nextship
# bun
bun add -g @pxilab/nextship
# Or run directly
npx @pxilab/nextship ship
bunx @pxilab/nextship shipQuick Start
- Configure your Next.js project for standalone output:
// next.config.js
module.exports = {
output: 'standalone',
}- Create a config file:
cp pxnship.config.example.js pxnship.config.js- Deploy:
pxnship shipUsage
# Full deployment (build → upload → restart)
pxnship ship
# Individual steps
pxnship build # Build Next.js application
pxnship upload # Upload files to server
pxnship restart # Restart PM2 application
# Options
pxnship ship --dry-run # Preview without making changes
pxnship ship --skip-build # Skip build step (use existing build)
pxnship ship --verbose # Enable detailed output
pxnship ship --config ./custom-config.js # Use custom config fileConfiguration
Config File
Create a config file in your project root. Supported formats:
pxnship.config.mjs(recommended - ES modules)pxnship.config.jspxnship.config.ts.pxnshiprcor.pxnshiprc.json
Example pxnship.config.mjs:
export default {
ssh: {
host: "server.example.com",
user: "deploy",
port: 22,
privateKeyPath: "~/.ssh/id_ed25519",
},
build: {
command: "bun run build",
standalone: true,
prepareLocally: true, // public/ ve static/ dosyalarını local'de standalone içine kopyalar
},
upload: {
remotePath: "/var/www/myapp",
exclude: [".git", "node_modules", ".env.local"],
},
pm2: {
appName: "myapp",
ecosystem: true, // true = auto-detect, false = don't use, "filename.js" = specific file
reload: true,
port: 3000, // Used when ecosystem is false
},
};Environment Variables
PXI NextShip loads environment files in the following order (later files override earlier ones):
.env- Base environment variables.env.local- Local overrides (add to.gitignore)
# .env.local (recommended for local development)
SSH_HOST=server.example.com
SSH_USER=deploy
SSH_PASSWORD=your-password
# Or use SSH key
SSH_KEY_PATH=~/.ssh/id_ed25519Available Variables:
# Required
SSH_HOST=server.example.com
SSH_USER=deploy
# Authentication (use one)
SSH_KEY=<private-key-content> # Inline private key (for CI/CD)
SSH_KEY_PATH=~/.ssh/id_ed25519 # Path to private key file
SSH_PASSWORD=<password> # Password auth
# Optional
SSH_PORT=22
REMOTE_PATH=/var/www/myapp
PM2_APP_NAME=myapp
BUILD_COMMAND="bun run build"GitHub Actions
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
- name: Deploy
run: bunx @pxilab/nextship ship
env:
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_USER: ${{ secrets.SSH_USER }}
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
PM2_APP_NAME: myapp
REMOTE_PATH: /var/www/myappServer Setup
Directory Structure
/var/www/myapp/
├── .next/
│ └── standalone/
│ ├── .next/
│ │ └── static/ # Build sırasında kopyalanır
│ ├── public/ # Build sırasında kopyalanır
│ ├── package.json # Next.js standalone build oluşturur
│ └── server.js
└── ecosystem.config.js # Optional (ayrıca upload edilmeli)Not:
prepareLocally: true(default) kullanıldığındapublic/ve.next/static/klasörleri build sırasında local'de.next/standalone/içine kopyalanır. Sunucuya sadece.next/standalone/gönderilir.package.jsonzaten standalone içinde.
PM2 Configuration
PXI NextShip supports three modes for PM2:
| ecosystem value | Behavior |
|-------------------|----------|
| true (default) | Auto-detect ecosystem.config.js in remote directory |
| false | Don't use ecosystem file, start with server.js directly |
| "custom.config.js" | Use a specific ecosystem file |
When ecosystem: false, you can specify a custom port with the port option.
PM2 Environment Variables
Inject environment variables when PM2 starts or reloads:
pm2: {
appName: "myapp",
ecosystem: false, // Standalone mode
port: 3000,
env: {
NODE_ENV: "production",
API_BASE_URL: process.env.API_BASE_URL,
DATABASE_URL: process.env.DATABASE_URL,
},
}Environment variables are passed to PM2 via shell environment and persist after pm2 save.
Note: When using ecosystem: true, define environment variables in your ecosystem.config.js file instead for better management.
PM2 Ecosystem File (Optional)
// ecosystem.config.js
module.exports = {
apps: [{
name: 'myapp',
script: '.next/standalone/server.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000,
},
}],
};Initial Server Setup
# Install PM2
npm install -g pm2
# Create directory
mkdir -p /var/www/myapp
chown deploy:deploy /var/www/myapp
# After first deploy
cd /var/www/myapp
pm2 start ecosystem.config.js # or: pm2 start .next/standalone/server.js --name myapp
pm2 save
pm2 startupPlatform Support
| Platform | Transfer Method | Performance | |----------|-----------------|-------------| | Linux / macOS | rsync | Fast (delta transfer) | | Windows + WSL | rsync via WSL | Fast (delta transfer) | | Windows (no rsync) | SFTP fallback | Slower (full file transfer) |
Windows Server Recommendation
For optimal performance on Windows servers, install WSL + rsync:
wsl --install -d Ubuntu
wsl sudo apt update && sudo apt install rsync -yWithout rsync, the tool automatically falls back to SFTP.
Programmatic API
import { loadConfig, runShip, runBuild, runUpload, runRestart } from '@pxilab/nextship';
const config = await loadConfig();
// Full deployment
await runShip(config);
// Or individual steps
await runBuild(config.build);
await runUpload(config.ssh, config.upload);
await runRestart(config.ssh, config.pm2);License
MIT
