Skip to content

Commit b4c0134

Browse files
Merge branch 'dev'
2 parents e4d4c62 + 165bbd3 commit b4c0134

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2444
-2679
lines changed

.github/dependabot.yml

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,9 @@ updates:
4444
schedule:
4545
interval: "daily"
4646
groups:
47-
dev-patch-updates:
48-
dependency-type: "development"
47+
patch-updates:
4948
update-types:
5049
- "patch"
51-
dev-minor-updates:
52-
dependency-type: "development"
50+
minor-updates:
5351
update-types:
5452
- "minor"
55-
prod-patch-updates:
56-
dependency-type: "production"
57-
update-types:
58-
- "patch"
59-
prod-minor-updates:
60-
dependency-type: "production"
61-
update-types:
62-
- "minor"

.github/workflows/linting.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- name: Set up Node.js
2727
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
2828
with:
29-
node-version: '22'
29+
node-version: '24'
3030

3131
- name: Install dependencies
3232
run: npm ci

.github/workflows/test.yml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Install Node
2020
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
2121
with:
22-
node-version: '22'
22+
node-version: '24'
2323

2424
- name: Copy config file
2525
run: cp config/config.example.yml config/config.yml
@@ -34,7 +34,7 @@ jobs:
3434
run: npm run set:oss
3535

3636
- name: Generate database migrations
37-
run: npm run db:sqlite:generate
37+
run: npm run db:generate
3838

3939
- name: Apply database migrations
4040
run: npm run db:sqlite:push
@@ -64,9 +64,6 @@ jobs:
6464
- name: Checkout repository
6565
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
6666

67-
- name: Copy config file
68-
run: cp config/config.example.yml config/config.yml
69-
7067
- name: Build Docker image sqlite
7168
run: make dev-build-sqlite
7269

@@ -76,8 +73,5 @@ jobs:
7673
- name: Checkout repository
7774
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
7875

79-
- name: Copy config file
80-
run: cp config/config.example.yml config/config.yml
81-
8276
- name: Build Docker image pg
8377
run: make dev-build-pg

Dockerfile

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,43 @@
11
FROM node:24-alpine AS builder
22

3-
# OCI Image Labels - Build Args for dynamic values
4-
ARG VERSION="dev"
5-
ARG REVISION=""
6-
ARG CREATED=""
7-
ARG LICENSE="AGPL-3.0"
8-
93
WORKDIR /app
104

115
ARG BUILD=oss
126
ARG DATABASE=sqlite
137

14-
# Derive title and description based on BUILD type
15-
ARG IMAGE_TITLE="Pangolin"
16-
ARG IMAGE_DESCRIPTION="Identity-aware VPN and proxy for remote access to anything, anywhere"
17-
18-
RUN apk add --no-cache curl tzdata python3 make g++
8+
RUN apk add --no-cache python3 make g++
199

2010
# COPY package.json package-lock.json ./
2111
COPY package*.json ./
2212
RUN npm ci
2313

2414
COPY . .
2515

26-
RUN echo "export * from \"./$DATABASE\";" > server/db/index.ts
27-
RUN echo "export const driver: \"pg\" | \"sqlite\" = \"$DATABASE\";" >> server/db/index.ts
28-
29-
RUN echo "export const build = \"$BUILD\" as \"saas\" | \"enterprise\" | \"oss\";" > server/build.ts
30-
31-
# Copy the appropriate TypeScript configuration based on build type
32-
RUN if [ "$BUILD" = "oss" ]; then cp tsconfig.oss.json tsconfig.json; \
33-
elif [ "$BUILD" = "saas" ]; then cp tsconfig.saas.json tsconfig.json; \
34-
elif [ "$BUILD" = "enterprise" ]; then cp tsconfig.enterprise.json tsconfig.json; \
35-
fi
36-
37-
# if the build is oss then remove the server/private directory
38-
RUN if [ "$BUILD" = "oss" ]; then rm -rf server/private; fi
39-
40-
RUN if [ "$DATABASE" = "pg" ]; then npx drizzle-kit generate --dialect postgresql --schema ./server/db/pg/schema --out init; else npx drizzle-kit generate --dialect $DATABASE --schema ./server/db/$DATABASE/schema --out init; fi
41-
42-
RUN mkdir -p dist
43-
RUN npm run next:build
44-
RUN node esbuild.mjs -e server/index.ts -o dist/server.mjs -b $BUILD
45-
RUN if [ "$DATABASE" = "pg" ]; then \
46-
node esbuild.mjs -e server/setup/migrationsPg.ts -o dist/migrations.mjs; \
47-
else \
48-
node esbuild.mjs -e server/setup/migrationsSqlite.ts -o dist/migrations.mjs; \
49-
fi
16+
RUN if [ "$BUILD" = "oss" ]; then rm -rf server/private; fi && \
17+
npm run set:$DATABASE && \
18+
npm run set:$BUILD && \
19+
npm run db:generate && \
20+
npm run build && \
21+
npm run build:cli
5022

5123
# test to make sure the build output is there and error if not
5224
RUN test -f dist/server.mjs
5325

54-
RUN npm run build:cli
55-
5626
# Prune dev dependencies and clean up to prepare for copy to runner
5727
RUN npm prune --omit=dev && npm cache clean --force
5828

5929
FROM node:24-alpine AS runner
6030

31+
# OCI Image Labels - Build Args for dynamic values
32+
ARG VERSION="dev"
33+
ARG REVISION=""
34+
ARG CREATED=""
35+
ARG LICENSE="AGPL-3.0"
36+
37+
# Derive title and description based on BUILD type
38+
ARG IMAGE_TITLE="Pangolin"
39+
ARG IMAGE_DESCRIPTION="Identity-aware VPN and proxy for remote access to anything, anywhere"
40+
6141
WORKDIR /app
6242

6343
# Only curl and tzdata needed at runtime - no build tools!
@@ -66,11 +46,10 @@ RUN apk add --no-cache curl tzdata
6646
# Copy pre-built node_modules from builder (already pruned to production only)
6747
# This includes the compiled native modules like better-sqlite3
6848
COPY --from=builder /app/node_modules ./node_modules
69-
7049
COPY --from=builder /app/.next/standalone ./
7150
COPY --from=builder /app/.next/static ./.next/static
7251
COPY --from=builder /app/dist ./dist
73-
COPY --from=builder /app/init ./dist/init
52+
COPY --from=builder /app/server/migrations ./dist/init
7453
COPY --from=builder /app/package.json ./package.json
7554

7655
COPY ./cli/wrapper.sh /usr/local/bin/pangctl

esbuild.mjs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import path from "path";
66
import fs from "fs";
77
// import { glob } from "glob";
88

9+
// Read default build type from server/build.ts
10+
let build = "oss";
11+
const buildFile = fs.readFileSync(path.resolve("server/build.ts"), "utf8");
12+
const m = buildFile.match(/export\s+const\s+build\s*=\s*["'](oss|saas|enterprise)["']/);
13+
if (m) build = m[1];
14+
915
const banner = `
1016
// patch __dirname
1117
// import { fileURLToPath } from "url";
@@ -37,7 +43,7 @@ const argv = yargs(hideBin(process.argv))
3743
describe: "Build type (oss, saas, enterprise)",
3844
type: "string",
3945
choices: ["oss", "saas", "enterprise"],
40-
default: "oss"
46+
default: build
4147
})
4248
.help()
4349
.alias("help", "h").argv;

install/main.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import (
66
"fmt"
77
"io"
88
"io/fs"
9-
"math/rand"
9+
"crypto/rand"
10+
"encoding/base64"
1011
"net"
1112
"net/http"
1213
"net/url"
@@ -592,17 +593,12 @@ func showSetupTokenInstructions(containerType SupportedContainer, dashboardDomai
592593
}
593594

594595
func generateRandomSecretKey() string {
595-
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
596-
const length = 32
597-
598-
var seededRand *rand.Rand = rand.New(
599-
rand.NewSource(time.Now().UnixNano()))
600-
601-
b := make([]byte, length)
602-
for i := range b {
603-
b[i] = charset[seededRand.Intn(len(charset))]
596+
secret := make([]byte, 32)
597+
_, err := rand.Read(secret)
598+
if err != nil {
599+
panic(fmt.Sprintf("Failed to generate random secret key: %v", err))
604600
}
605-
return string(b)
601+
return base64.StdEncoding.EncodeToString(secret)
606602
}
607603

608604
func getPublicIP() string {

messages/en-US.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,15 @@
14361436
"billingUsersInfo": "You're charged for each user in the organization. Billing is calculated daily based on the number of active user accounts in your org.",
14371437
"billingDomainInfo": "You're charged for each domain in the organization. Billing is calculated daily based on the number of active domain accounts in your org.",
14381438
"billingRemoteExitNodesInfo": "You're charged for each managed Node in the organization. Billing is calculated daily based on the number of active managed Nodes in your org.",
1439+
"billingLicenseKeys": "License Keys",
1440+
"billingLicenseKeysDescription": "Manage your license key subscriptions",
1441+
"billingLicenseSubscription": "License Subscription",
1442+
"billingInactive": "Inactive",
1443+
"billingLicenseItem": "License Item",
1444+
"billingQuantity": "Quantity",
1445+
"billingTotal": "total",
1446+
"billingModifyLicenses": "Modify License Subscription",
1447+
"billingPricingCalculatorLink": "View Pricing Calculator",
14391448
"domainNotFound": "Domain Not Found",
14401449
"domainNotFoundDescription": "This resource is disabled because the domain no longer exists our system. Please set a new domain for this resource.",
14411450
"failed": "Failed",
@@ -2113,6 +2122,32 @@
21132122
}
21142123
}
21152124
},
2125+
"newPricingLicenseForm": {
2126+
"title": "Get a license",
2127+
"description": "Choose a plan and tell us how you plan to use Pangolin.",
2128+
"chooseTier": "Choose your plan",
2129+
"viewPricingLink": "See pricing, features, and limits",
2130+
"tiers": {
2131+
"starter": {
2132+
"title": "Starter",
2133+
"description": "Enterprise features, 25 users, 25 sites, and community support."
2134+
},
2135+
"scale": {
2136+
"title": "Scale",
2137+
"description": "Enterprise features, 50 users, 50 sites, and priority support."
2138+
}
2139+
},
2140+
"personalUseOnly": "Personal use only (free license — no checkout)",
2141+
"buttons": {
2142+
"continueToCheckout": "Continue to Checkout"
2143+
},
2144+
"toasts": {
2145+
"checkoutError": {
2146+
"title": "Checkout error",
2147+
"description": "Could not start checkout. Please try again."
2148+
}
2149+
}
2150+
},
21162151
"priority": "Priority",
21172152
"priorityDescription": "Higher priority routes are evaluated first. Priority = 100 means automatic ordering (system decides). Use another number to enforce manual priority.",
21182153
"instanceName": "Instance Name",

0 commit comments

Comments
 (0)