2024-04-14 18:02:55 +02:00
# @push.rocks/smartnginx
2025-11-27 13:14:58 +00:00
Control Nginx programmatically from Node.js with full TypeScript support 🚀
## Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/ ](https://community.foss.global/ ). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/ ](https://code.foss.global/ ) account to submit Pull Requests directly.
## Features
- 🎯 **Dynamic Configuration ** - Generate and manage Nginx configs on the fly
- 🔒 **SSL/TLS Ready ** - Built-in support for SSL certificates with automatic HTTP→HTTPS redirects
- 🔄 **Hot Reload ** - Apply configuration changes without downtime
- 📦 **Zero-Config Defaults ** - Self-signed certificates auto-generated for immediate testing
- 🎛️ **Reverse Proxy Made Easy ** - Set up proxy hosts with a single method call
- 🧠 **Smart Diffing ** - Only reloads Nginx when configurations actually change
- 📝 **TypeScript First ** - Full type definitions included
2024-04-14 18:02:55 +02:00
## Install
2025-11-27 13:14:58 +00:00
2024-04-14 18:02:55 +02:00
```bash
2025-11-27 13:14:58 +00:00
pnpm add @push .rocks/smartnginx
# or
npm install @push .rocks/smartnginx
2024-04-14 18:02:55 +02:00
```
2025-11-27 13:14:58 +00:00
> **Prerequisites**: Nginx must be installed and available in your system PATH.
## Quick Start
```typescript
import { SmartNginx } from '@push .rocks/smartnginx';
// Create a SmartNginx instance with a default fallback URL
const nginx = new SmartNginx({
defaultProxyUrl: 'https://your-default-site.com'
});
// Add a reverse proxy host
nginx.addHostCandidate({
hostName: 'api.example.com',
destination: 'localhost',
destinationPort: 3000,
privateKey: '<your-ssl-private-key>',
publicKey: '<your-ssl-certificate>'
});
// Deploy and start Nginx
await nginx.deploy();
```
That's it! Your reverse proxy is now running 🎉
2024-04-14 18:02:55 +02:00
## Usage
2025-11-27 13:14:58 +00:00
### Creating the SmartNginx Instance
The `SmartNginx` class is your main interface for managing Nginx:
2024-04-14 18:02:55 +02:00
```typescript
2025-11-27 13:14:58 +00:00
import { SmartNginx } from '@push .rocks/smartnginx';
const nginx = new SmartNginx({
defaultProxyUrl: 'https://fallback.example.com', // Where unmatched requests go
logger: myCustomLogger // Optional: pass a @push .rocks/smartlog instance
});
2024-04-14 18:02:55 +02:00
```
2025-11-27 13:14:58 +00:00
### Adding Host Configurations
Each host represents a domain/subdomain with its proxy rules and SSL certificates:
2024-04-14 18:02:55 +02:00
```typescript
2025-11-27 13:14:58 +00:00
// Add a host using addHostCandidate()
const myHost = nginx.addHostCandidate({
hostName: 'app.example.com', // Domain name
destination: '127.0.0.1', // Backend server address
destinationPort: 8080, // Backend port
privateKey: sslPrivateKeyPem, // SSL private key (PEM format)
publicKey: sslCertificatePem // SSL certificate (PEM format)
2024-04-14 18:02:55 +02:00
});
```
2025-11-27 13:14:58 +00:00
### Multi-Host Setup
Run multiple sites through a single Nginx instance:
2024-04-14 18:02:55 +02:00
```typescript
2025-11-27 13:14:58 +00:00
// Production API
nginx.addHostCandidate({
hostName: 'api.myapp.com',
2024-04-14 18:02:55 +02:00
destination: 'localhost',
2025-11-27 13:14:58 +00:00
destinationPort: 3000,
privateKey: apiPrivateKey,
publicKey: apiCertificate
});
// Admin panel
nginx.addHostCandidate({
hostName: 'admin.myapp.com',
destination: 'localhost',
destinationPort: 4000,
privateKey: adminPrivateKey,
publicKey: adminCertificate
});
// Staging environment
nginx.addHostCandidate({
hostName: 'staging.myapp.com',
destination: '192.168.1.100',
2024-04-14 18:02:55 +02:00
destinationPort: 8080,
2025-11-27 13:14:58 +00:00
privateKey: stagingPrivateKey,
publicKey: stagingCertificate
2024-04-14 18:02:55 +02:00
});
2025-11-27 13:14:58 +00:00
// Deploy all at once
await nginx.deploy();
2024-04-14 18:02:55 +02:00
```
2025-11-27 13:14:58 +00:00
### Deploying Configurations
The `deploy()` method is smart about changes:
2024-04-14 18:02:55 +02:00
```typescript
2025-11-27 13:14:58 +00:00
// First deploy - writes configs and starts Nginx
await nginx.deploy();
// Add more hosts dynamically
nginx.addHostCandidate({
hostName: 'newsite.example.com',
2024-04-14 18:02:55 +02:00
destination: 'localhost',
2025-11-27 13:14:58 +00:00
destinationPort: 5000,
privateKey: newPrivateKey,
publicKey: newCertificate
2024-04-14 18:02:55 +02:00
});
2025-11-27 13:14:58 +00:00
// Second deploy - detects changes, updates configs, hot-reloads Nginx
await nginx.deploy();
// If you call deploy() with no changes, it skips the reload (efficient!)
await nginx.deploy(); // → "hosts have not diverged, skipping nginx reload"
```
### Querying Deployed Hosts
```typescript
// Get all deployed hosts
const hosts = await nginx.listDeployedHosts();
console.log(`Running ${hosts.length} hosts` );
// Find a specific host by domain
const apiHost = nginx.getDeployedNginxHostByHostName('api.example.com');
if (apiHost) {
console.log(`API proxying to ${apiHost.destination}:${apiHost.destinationPort}` );
}
```
### Removing Hosts
```typescript
const hostToRemove = nginx.getDeployedNginxHostByHostName('staging.myapp.com');
if (hostToRemove) {
await nginx.removeDeployedHost(hostToRemove);
// Nginx automatically reloaded with updated config
}
2024-04-14 18:02:55 +02:00
```
2025-11-27 13:14:58 +00:00
### Stopping Nginx
2024-04-14 18:02:55 +02:00
```typescript
2025-11-27 13:14:58 +00:00
// Gracefully stop the Nginx process
await nginx.stop();
2024-04-14 18:02:55 +02:00
```
2025-11-27 13:14:58 +00:00
## Generated Configuration
SmartNginx generates production-ready Nginx configurations:
**For each host, you get:**
- HTTP (port 80) → HTTPS (port 443) automatic redirect
- Upstream with keepalive connections (100 idle connections)
- WebSocket-friendly proxy settings (HTTP/1.1, no buffering)
- Proper proxy headers (`X-Real-IP` , `X-Forwarded-For` , `X-Forwarded-Proto` )
- Smart failover (`proxy_next_upstream` on errors, timeouts, 404/429/500/502)
**Default server:**
- Self-signed certificate for unmatched domains
- Redirects to your configured `defaultProxyUrl`
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ SmartNginx │
├─────────────────────────────────────────────────────────────┤
│ hostCandidates[] → deploy() → deployedHosts[] │
│ ↓ │
│ NginxProcess │
│ (start/reload/stop) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Generated Files │
├─────────────────────────────────────────────────────────────┤
│ nginxconfig/ │
│ ├── nginx.conf (main config) │
│ └── hosts/ │
│ ├── default.private.pem (self-signed key) │
│ ├── default.public.pem (self-signed cert) │
│ ├── api.example.com.conf │
│ ├── api.example.com.private.pem │
│ └── api.example.com.public.pem │
└─────────────────────────────────────────────────────────────┘
```
## API Reference
### SmartNginx
| Method | Description |
|--------|-------------|
| `addHostCandidate(config)` | Add a new host configuration |
| `deploy()` | Write configs and start/reload Nginx |
| `listDeployedHosts()` | Get all currently deployed hosts |
| `getDeployedNginxHostByHostName(hostname)` | Find a host by domain name |
| `removeDeployedHost(host)` | Remove a host and reload Nginx |
| `stop()` | Gracefully stop Nginx |
### IHostConfig
```typescript
interface IHostConfig {
hostName: string; // Domain name (e.g., 'api.example.com')
destination: string; // Backend server IP/hostname
destinationPort: number; // Backend port
privateKey: string; // SSL private key (PEM)
publicKey: string; // SSL certificate (PEM)
}
```
### NginxHost
Each host instance exposes:
- `hostName` - The configured domain
- `destination` - Backend address
- `destinationPort` - Backend port
- `configString` - The generated Nginx config (after deploy)
- `deploy()` - Write this host's config files
2024-04-14 18:02:55 +02:00
## License and Legal Information
2025-11-27 13:14:58 +00:00
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license ](license ) file within this repository.
2024-04-14 18:02:55 +02:00
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
### Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
### Company Information
2025-11-27 13:14:58 +00:00
Task Venture Capital GmbH
2024-04-14 18:02:55 +02:00
Registered at District court Bremen HRB 35230 HB, Germany
For any legal inquiries or if you require further information, please contact us via email at hello@task .vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.