Skip to content

Instantly share code, notes, and snippets.

@thrawn01
Created August 12, 2025 04:07
Show Gist options
  • Save thrawn01/0ad114e7eb77f4332eb56ed17651224b to your computer and use it in GitHub Desktop.
Save thrawn01/0ad114e7eb77f4332eb56ed17651224b to your computer and use it in GitHub Desktop.
const pulumi = require("@pulumi/pulumi");
const uncloud = require("@uncloud/pulumi");
// Configure the Uncloud provider
const provider = new uncloud.Provider("uncloud-provider", {
// Connect to any machine in the cluster via SSH
sshHost: "[email protected]",
sshPort: 22,
// Optional: specify cluster if you have multiple
cluster: "production",
// Optional: SSH key path (defaults to ~/.ssh/id_rsa)
sshKeyPath: "~/.ssh/uncloud_key"
});
// Create a persistent volume for PostgreSQL data
const pgVolume = new uncloud.Volume("postgres-data", {
name: "postgres-data",
// Uncloud manages volumes across cluster nodes
}, { provider });
// Deploy PostgreSQL database
const database = new uncloud.Service("postgres", {
name: "postgres",
image: "postgres:15-alpine",
// Environment variables for PostgreSQL
environment: {
POSTGRES_DB: "webapp",
POSTGRES_USER: "webapp_user",
POSTGRES_PASSWORD: pulumi.secret("super_secret_password"),
PGDATA: "/var/lib/postgresql/data/pgdata"
},
// Mount the persistent volume
volumes: [{
name: pgVolume.name,
mountPath: "/var/lib/postgresql/data"
}],
// Internal port for database connections
ports: [{
containerPort: 5432,
protocol: "tcp"
}],
// Deployment configuration
replicas: 1, // Database should typically be single instance
// Resource limits
resources: {
memory: "512Mi",
cpu: "0.5"
},
// Health check
healthCheck: {
command: ["pg_isready", "-U", "webapp_user", "-d", "webapp"],
intervalSeconds: 10,
timeoutSeconds: 5,
retries: 3
},
// Restart policy
restartPolicy: "always"
}, { provider });
// Create a volume for web app uploads/data (optional)
const appVolume = new uncloud.Volume("webapp-uploads", {
name: "webapp-uploads"
}, { provider });
// Deploy the web application
const webApp = new uncloud.Service("webapp", {
name: "webapp",
image: "mycompany/webapp:latest",
// Environment variables for the web app
environment: {
DATABASE_URL: pulumi.interpolate`postgresql://webapp_user:super_secret_password@${database.internalHostname}:5432/webapp`,
NODE_ENV: "production",
PORT: "3000"
},
// Mount uploads volume
volumes: [{
name: appVolume.name,
mountPath: "/app/uploads"
}],
// Port configuration
ports: [{
containerPort: 3000,
protocol: "http",
// Expose via custom domain with automatic HTTPS
publicDomain: "myapp.example.com"
}],
// Scale to multiple replicas for high availability
replicas: 3,
// Resource limits
resources: {
memory: "256Mi",
cpu: "0.25"
},
// Health check
healthCheck: {
httpPath: "/health",
port: 3000,
intervalSeconds: 15,
timeoutSeconds: 10,
retries: 3
},
// Deployment strategy
deploymentStrategy: {
type: "rolling",
maxUnavailable: 1,
maxSurge: 1
},
// Dependencies - ensure database starts first
dependsOn: [database],
// Restart policy
restartPolicy: "always"
}, { provider });
// Optional: Deploy a Redis cache
const cache = new uncloud.Service("redis", {
name: "redis",
image: "redis:7-alpine",
ports: [{
containerPort: 6379,
protocol: "tcp"
}],
replicas: 1,
resources: {
memory: "128Mi",
cpu: "0.1"
},
// Redis persistence
volumes: [{
name: "redis-data",
mountPath: "/data"
}],
healthCheck: {
command: ["redis-cli", "ping"],
intervalSeconds: 10,
timeoutSeconds: 3,
retries: 3
}
}, { provider });
// Optional: Create a network policy (if Uncloud supports it)
const networkPolicy = new uncloud.NetworkPolicy("webapp-network", {
name: "webapp-network",
// Allow webapp to communicate with database and cache
rules: [{
from: [{ service: webApp.name }],
to: [
{ service: database.name, ports: [5432] },
{ service: cache.name, ports: [6379] }
]
}],
// Allow external traffic to webapp
ingress: [{
from: "external",
to: { service: webApp.name, ports: [3000] }
}]
}, { provider });
// Output important information
exports.webAppUrl = webApp.publicUrl;
exports.webAppInternalHostname = webApp.internalHostname;
exports.databaseInternalHostname = database.internalHostname;
exports.clusterDomain = webApp.clusterDomain;
// Output cluster information
exports.cluster = {
machines: provider.clusterMachines,
domain: provider.clusterDomain
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment