freeschema 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,207 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ const { spawnSync } = require('child_process');
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ const VERSION = require('../package.json').version;
10
+ const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
11
+
12
+ const args = process.argv.slice(2);
13
+ const command = args[0];
14
+
15
+ // ── helpers ──────────────────────────────────────────────────────────────────
16
+
17
+ function die(msg) {
18
+ console.error(`\nError: ${msg}\n`);
19
+ process.exit(1);
20
+ }
21
+
22
+ function copyRecursive(src, dest) {
23
+ if (fs.statSync(src).isDirectory()) {
24
+ if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
25
+ for (const entry of fs.readdirSync(src)) {
26
+ copyRecursive(path.join(src, entry), path.join(dest, entry));
27
+ }
28
+ } else {
29
+ fs.copyFileSync(src, dest);
30
+ }
31
+ }
32
+
33
+ function runCompose(composeArgs) {
34
+ const cwd = process.cwd();
35
+
36
+ if (!fs.existsSync(path.join(cwd, 'docker-compose.yml'))) {
37
+ die('No docker-compose.yml found in the current directory.\nRun `freeschema init` first.');
38
+ }
39
+
40
+ const result = spawnSync('docker', ['compose', ...composeArgs], {
41
+ stdio: 'inherit',
42
+ cwd,
43
+ });
44
+
45
+ if (result.error) die(`Could not run docker: ${result.error.message}`);
46
+ if (result.status !== 0) process.exit(result.status);
47
+ }
48
+
49
+ // ── commands ──────────────────────────────────────────────────────────────────
50
+
51
+ function cmdInit() {
52
+ const target = process.cwd();
53
+ console.log(`Initializing FreeSchema in ${target}\n`);
54
+
55
+ for (const entry of fs.readdirSync(TEMPLATES_DIR)) {
56
+ const src = path.join(TEMPLATES_DIR, entry);
57
+ const dest = path.join(target, entry);
58
+
59
+ if (fs.existsSync(dest)) {
60
+ console.log(` skip ${entry} (already exists)`);
61
+ continue;
62
+ }
63
+
64
+ copyRecursive(src, dest);
65
+ console.log(` create ${entry}`);
66
+ }
67
+
68
+ // .env from example if not present
69
+ const envFile = path.join(target, '.env');
70
+ const envExample = path.join(target, '.env.example');
71
+ if (!fs.existsSync(envFile) && fs.existsSync(envExample)) {
72
+ fs.copyFileSync(envExample, envFile);
73
+ console.log(' create .env (copied from .env.example)');
74
+ }
75
+
76
+ // .env.frontend from example if not present
77
+ const envFrontend = path.join(target, '.env.frontend');
78
+ const envFrontendExample = path.join(target, '.env.frontend.example');
79
+ if (!fs.existsSync(envFrontend) && fs.existsSync(envFrontendExample)) {
80
+ fs.copyFileSync(envFrontendExample, envFrontend);
81
+ console.log(' create .env.frontend (copied from .env.frontend.example)');
82
+ }
83
+
84
+ console.log(`
85
+ Done! Next steps:
86
+ 1. Edit .env with your database, MQTT, SMTP, and JWT settings
87
+ 2. (Optional) Add SQL seed files to seed-db/
88
+ 3. Run one of:
89
+ freeschema start # external DB + MQTT
90
+ freeschema start --local-db # spin up local MySQL
91
+ freeschema start --local-db --local-mqtt # spin up MySQL + MQTT broker
92
+ `);
93
+ }
94
+
95
+ function cmdStart() {
96
+ const profiles = [];
97
+ const flags = args.slice(1);
98
+
99
+ if (flags.includes('--local-db') || flags.includes('--db')) profiles.push('--profile', 'local-db');
100
+ if (flags.includes('--local-mqtt') || flags.includes('--mqtt')) profiles.push('--profile', 'local-mqtt');
101
+
102
+ console.log('Pulling latest FreeSchema images…');
103
+ runCompose([...profiles, 'pull']);
104
+
105
+ console.log('\nStarting FreeSchema services…');
106
+ runCompose([...profiles, 'up', '-d']);
107
+
108
+ console.log('\nFreeSchema is running.');
109
+ console.log(' Logs: freeschema logs');
110
+ console.log(' Status: freeschema status');
111
+ console.log(' Stop: freeschema stop');
112
+ }
113
+
114
+ function cmdStop() {
115
+ console.log('Stopping FreeSchema services…');
116
+ runCompose(['down']);
117
+ }
118
+
119
+ function cmdRestart() {
120
+ const service = args[1];
121
+ service ? runCompose(['restart', service]) : runCompose(['restart']);
122
+ }
123
+
124
+ function cmdStatus() {
125
+ runCompose(['ps']);
126
+ }
127
+
128
+ function cmdLogs() {
129
+ const service = args[1];
130
+ const follow = !args.includes('--no-follow');
131
+ const logArgs = ['logs'];
132
+ if (follow) logArgs.push('--follow');
133
+ if (service) logArgs.push(service);
134
+ runCompose(logArgs);
135
+ }
136
+
137
+ function cmdPull() {
138
+ console.log('Pulling latest FreeSchema images…');
139
+ runCompose(['pull']);
140
+ console.log('\nDone. Run `freeschema restart` to apply.');
141
+ }
142
+
143
+ function cmdDown() {
144
+ const withVolumes = args.includes('--volumes') || args.includes('-v');
145
+ if (withVolumes) {
146
+ console.log('Removing containers and volumes…');
147
+ runCompose(['down', '--volumes']);
148
+ } else {
149
+ console.log('Removing containers…');
150
+ runCompose(['down']);
151
+ }
152
+ }
153
+
154
+ function cmdHelp() {
155
+ console.log(`
156
+ FreeSchema CLI v${VERSION}
157
+
158
+ Usage:
159
+ freeschema <command> [options]
160
+
161
+ Commands:
162
+ init Copy config files into the current directory
163
+ start Pull latest images and start all services
164
+ --local-db Also start the bundled MySQL container
165
+ --local-mqtt Also start the bundled MQTT broker
166
+ stop Stop all running services
167
+ restart [service] Restart all services, or a single one
168
+ status Show container status (docker compose ps)
169
+ logs [service] Stream logs for all services, or one
170
+ --no-follow Print logs without following
171
+ pull Pull latest Docker images without restarting
172
+ down [-v] Remove containers (add -v to also remove volumes)
173
+
174
+ Examples:
175
+ freeschema init
176
+ freeschema start --local-db --local-mqtt
177
+ freeschema logs wico-server
178
+ freeschema restart node-server
179
+ freeschema down -v
180
+ `);
181
+ }
182
+
183
+ // ── dispatch ──────────────────────────────────────────────────────────────────
184
+
185
+ switch (command) {
186
+ case 'init': cmdInit(); break;
187
+ case 'start': cmdStart(); break;
188
+ case 'stop': cmdStop(); break;
189
+ case 'restart': cmdRestart(); break;
190
+ case 'status': cmdStatus(); break;
191
+ case 'logs': cmdLogs(); break;
192
+ case 'pull': cmdPull(); break;
193
+ case 'down': cmdDown(); break;
194
+ case '--version':
195
+ case '-v':
196
+ console.log(VERSION);
197
+ break;
198
+ case '--help':
199
+ case '-h':
200
+ case undefined:
201
+ cmdHelp();
202
+ break;
203
+ default:
204
+ console.error(`Unknown command: ${command}`);
205
+ cmdHelp();
206
+ process.exit(1);
207
+ }
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "freeschema",
3
+ "version": "1.0.0",
4
+ "description": "FreeSchema — self-hosted deployment CLI",
5
+ "keywords": ["freeschema", "self-hosted", "docker"],
6
+ "homepage": "https://freeschema.com",
7
+ "license": "MIT",
8
+ "bin": {
9
+ "freeschema": "./bin/freeschema.js"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "templates/"
14
+ ],
15
+ "engines": {
16
+ "node": ">=16.0.0"
17
+ }
18
+ }
@@ -0,0 +1,123 @@
1
+ # ====================================
2
+ # APPLICATION SETTINGS
3
+ # ====================================
4
+ JWT_SECRET=""
5
+ LICENSE_KEY=
6
+ MFTSCCS_AI_URL=
7
+ WIDGETS={"documentationWidget":0}
8
+
9
+ # ====================================
10
+ # DATABASE CONFIGURATION
11
+ # ====================================
12
+
13
+ # Database Mode: "local" or "external"
14
+ # - local: Use Docker MySQL container (requires --local-db flag)
15
+ # - external: Use external MySQL server (AWS RDS, Azure, Google Cloud SQL, self-hosted)
16
+ DB_MODE=local
17
+
18
+ # ─────────────────────────────────────────────────────────────
19
+ # ACTIVE DATABASE CONNECTION (Used by services)
20
+ # ─────────────────────────────────────────────────────────────
21
+
22
+ # === LOCAL MODE (default) ===
23
+ DB_HOST=mysql-server
24
+ DB_PORT=3306
25
+ DB_USER=freeschema
26
+ DB_PASSWORD=Freeschema@123
27
+ DB_DATABASE=freeschema_db
28
+ DB_SESSION_DATABASE=sessions_db
29
+
30
+ # === EXTERNAL MODE (uncomment and modify when DB_MODE=external) ===
31
+ # DB_HOST=your-external-db-host.com
32
+ # DB_PORT=3306
33
+ # DB_USER=your-db-user
34
+ # DB_PASSWORD=your-db-password
35
+ # DB_DATABASE=your-database-name
36
+ # DB_SESSION_DATABASE=your-session-database
37
+
38
+ # ─────────────────────────────────────────────────────────────
39
+ # LOCAL DOCKER MYSQL SETTINGS
40
+ # ─────────────────────────────────────────────────────────────
41
+ MYSQL_PORT=3308
42
+ MYSQL_ROOT_PASSWORD=Admin@Freeschema123
43
+ MYSQL_USER=freeschema
44
+ MYSQL_PASSWORD=Freeschema@123
45
+ MYSQL_DATABASE=freeschema_db
46
+ MYSQL_SESSION_DATABASE=sessions_db
47
+
48
+ # MySQL Performance Settings
49
+ MYSQL_MAX_CONNECTIONS=10000
50
+ MYSQL_INNODB_BUFFER_POOL_SIZE=3G
51
+ MYSQL_INNODB_LOG_BUFFER_SIZE=128M
52
+ MYSQL_INNODB_REDO_LOG_CAPACITY=2G
53
+
54
+ # ====================================
55
+ # MQTT BROKER CONFIGURATION
56
+ # ====================================
57
+ MQTT_USERNAME=freeschema
58
+ MQTT_PASSWORD=freeschema
59
+ MQTT_HOST=localhost
60
+ MQTT_PORT=1884
61
+ MQTT_ALLOW_ANONYMOUS=true
62
+ MQTT_PERSISTENCE=true
63
+
64
+ # ====================================
65
+ # SERVICE PORTS CONFIGURATION
66
+ # ====================================
67
+ ACCESS_CONTROL_PORT=7070
68
+ WICO_PORT=7071
69
+ NODE_SERVER_PORT=5051
70
+ NODE_CACHE_SERVER_PORT=5055
71
+ LOG_SERVER_PORT=5050
72
+ NGINX_PORT=80
73
+ NGINX_SSL_PORT=443
74
+ CORS_ORIGIN=*
75
+
76
+ # ====================================
77
+ # FTP CONFIGURATION
78
+ # ====================================
79
+ FTP_IMAGE_UPLOAD_API_URL=
80
+ FTP_SERVER_URL=
81
+ FTP_USERNAME=
82
+ FTP_PASSWORD=
83
+
84
+ # ====================================
85
+ # SMTP SETTINGS
86
+ # ====================================
87
+ SMTP_HOST=
88
+ SMTP_USERNAME=
89
+ SMTP_PASSWORD=
90
+ SMTP_PORT=
91
+ SMTP_FROM_ADDRESS=
92
+
93
+ # ====================================
94
+ # OAUTH & INTEGRATIONS
95
+ # ====================================
96
+ LINKEDIN_CLIENT_ID=""
97
+ LINKEDIN_SECRET=""
98
+
99
+ # ====================================
100
+ # PAYMENT GATEWAY (STRIPE)
101
+ # ====================================
102
+ STRIPE_SECRET=""
103
+ WEBHOOK_KEY=""
104
+ STRIPE_TEST_SECRET=""
105
+ WEBHOOK_TEST_KEY=""
106
+
107
+ # ====================================
108
+ # CACHE SERVERS
109
+ # ====================================
110
+ CACHE_SERVERS=[{"server":"http://localhost/cache-api","lat":40.7128,"lon":-74.0060}]
111
+
112
+ # ====================================
113
+ # ENVIRONMENT SETTINGS
114
+ # ====================================
115
+ NODE_ENV=production
116
+ ASPNETCORE_ENVIRONMENT=Production
117
+ DISABLE_SWAGGER=true
118
+
119
+ # ====================================
120
+ # CLIENT CREDENTIALS (Optional)
121
+ # ====================================
122
+ CLIENT_ID=
123
+ CLIENT_SECRET=
@@ -0,0 +1,22 @@
1
+ VITE_BASE_URL=/node-api/api/v1
2
+ VITE_BASE_NODE_URL=/node-api
3
+ VITE_BOOM_URL=/wico-api
4
+ VITE_AI_URL=https://www.devai.freeschema.com/api
5
+ VITE_CLIENT_ID=852081598920-nv82tkhbiiklg0790q12m8o7v1co9f7i.apps.googleusercontent.com
6
+ VITE_LOGSERVER=/log-api
7
+ VITE_ENABLE_SW=false
8
+ VITE_ACCESS_CONTROL_URL=/access-control-api
9
+ VITE_DISCUSSION_COMMUNITY=100000609
10
+ VITE_AI_WIDGET=100000684
11
+ VITE_VISUAL_PROTOTYPE_WIDGET=100000701
12
+ VITE_VIDEO_TUTORIAL_WIDGET=100000712
13
+ VITE_SUBSCRIPTION_ID=100000741
14
+ VITE_DOCUMENTATION_PREVIEW_WIDGET=100000767
15
+ VITE_FOLDER_WIDGET=100000812
16
+ VITE_ASSETS_WIDGET=100000874
17
+ VITE_TRANSFER_WIDGET=100000992
18
+ VITE_DEPLOY_URL=
19
+ VITE_AGENT_URL=https://wico-ai.freeschema.com
20
+ VITE_BASE_ROUTE=/wico
21
+ VITE_DEV_BASE=http://localhost:5173
22
+ VITE_CDN_BASE=https://cdn.jsdelivr.net/gh/nischaldev/sleepinghats-cdn@master
@@ -0,0 +1,279 @@
1
+ services:
2
+ mysql-init:
3
+ image: mysql:8.0
4
+ profiles:
5
+ - local-db
6
+ volumes:
7
+ - mysql-data:/var/lib/mysql
8
+ command: >
9
+ bash -c "
10
+ chown -R mysql:mysql /var/lib/mysql &&
11
+ chmod -R 755 /var/lib/mysql &&
12
+ echo 'MySQL volume permissions fixed'
13
+ "
14
+ restart: "no"
15
+
16
+ mysql:
17
+ image: mysql:8.0
18
+ container_name: ${CONTAINER_PREFIX:-}mysql-server
19
+ profiles:
20
+ - local-db
21
+ env_file:
22
+ - .env
23
+ environment:
24
+ MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-Admin@Freeschema123}
25
+ MYSQL_DATABASE: ${MYSQL_DATABASE:-freeschema_db}
26
+ MYSQL_USER: ${MYSQL_USER:-freeschema}
27
+ MYSQL_PASSWORD: ${MYSQL_PASSWORD:-Freeschema@123}
28
+ ports:
29
+ - "${MYSQL_PORT:-3308}:3306"
30
+ volumes:
31
+ - mysql-data:/var/lib/mysql
32
+ - ./seed-db:/docker-entrypoint-initdb.d:ro
33
+ - ./my_custom.cnf:/etc/mysql/conf.d/my_custom.cnf:ro
34
+ networks:
35
+ - freeschema-network
36
+ restart: unless-stopped
37
+ depends_on:
38
+ - mysql-init
39
+ user: "999:999"
40
+ command: >
41
+ --default-authentication-plugin=mysql_native_password
42
+ healthcheck:
43
+ test: ["CMD-SHELL", "mysqladmin ping -h localhost -u${MYSQL_USER:-freeschema} -p${MYSQL_PASSWORD:-Freeschema@123} --silent"]
44
+ interval: 10s
45
+ retries: 60
46
+ start_period: 30s
47
+ timeout: 10s
48
+
49
+ mqtt-broker:
50
+ image: eclipse-mosquitto:2.0
51
+ container_name: ${CONTAINER_PREFIX:-}mqtt-broker
52
+ profiles:
53
+ - local-mqtt
54
+ ports:
55
+ - "${MQTT_EXTERNAL_PORT:-1884}:1883"
56
+ volumes:
57
+ - ./mosquitto/config:/mosquitto/config:ro
58
+ - ./mosquitto/data:/mosquitto/data
59
+ - ./mosquitto/log:/mosquitto/log
60
+ networks:
61
+ - freeschema-network
62
+ restart: unless-stopped
63
+
64
+ access-control-server:
65
+ image: mentorayush/access-control-server:latest
66
+ container_name: ${CONTAINER_PREFIX:-}access-control-server
67
+ extra_hosts:
68
+ - "host.docker.internal:host-gateway"
69
+ env_file:
70
+ - .env
71
+ environment:
72
+ - FreeSchemaSetting__ConnectionSetting__DefaultConnection=server=${DB_HOST};port=${DB_PORT};user=${DB_USER};password=${DB_PASSWORD};database=${DB_DATABASE};AllowPublicKeyRetrieval=True;
73
+ - FreeSchemaSetting__ConnectionSetting__SessionConnection=server=${DB_HOST};port=${DB_PORT};user=${DB_USER};password=${DB_PASSWORD};database=${DB_SESSION_DATABASE};AllowPublicKeyRetrieval=True;
74
+ - FreeSchemaSetting__Broker__Mqtt__BrokerUrl=${MQTT_HOST}
75
+ - FreeSchemaSetting__Broker__Mqtt__Port=${MQTT_PORT}
76
+ - FreeSchemaSetting__Broker__Mqtt__Username=${MQTT_USERNAME}
77
+ - FreeSchemaSetting__Broker__Mqtt__Password=${MQTT_PASSWORD}
78
+ - FreeSchemaSetting__AccessControlBaseUrl=http://access-control-server:7000/api/
79
+ networks:
80
+ - freeschema-network
81
+ restart: unless-stopped
82
+ healthcheck:
83
+ test: ["CMD-SHELL", "curl -sI http://localhost:7000/health || exit 1"]
84
+ interval: 10s
85
+ retries: 5
86
+ start_period: 30s
87
+ timeout: 5s
88
+
89
+ wico-server:
90
+ image: mentorayush/wico-server:latest
91
+ container_name: ${CONTAINER_PREFIX:-}wico-server
92
+ extra_hosts:
93
+ - "host.docker.internal:host-gateway"
94
+ env_file:
95
+ - .env
96
+ environment:
97
+ - FreeSchemaSetting__ConnectionSetting__DefaultConnection=server=${DB_HOST};port=${DB_PORT};user=${DB_USER};password=${DB_PASSWORD};database=${DB_DATABASE};AllowPublicKeyRetrieval=True;
98
+ - FreeSchemaSetting__ConnectionSetting__SessionConnection=server=${DB_HOST};port=${DB_PORT};user=${DB_USER};password=${DB_PASSWORD};database=${DB_SESSION_DATABASE};AllowPublicKeyRetrieval=True;
99
+ - FreeSchemaSetting__Broker__Type=Mqtt
100
+ - FreeSchemaSetting__Broker__Mqtt__BrokerUrl=${MQTT_HOST}
101
+ - FreeSchemaSetting__Broker__Mqtt__Port=${MQTT_PORT}
102
+ - FreeSchemaSetting__Broker__Mqtt__Username=${MQTT_USERNAME}
103
+ - FreeSchemaSetting__Broker__Mqtt__Password=${MQTT_PASSWORD}
104
+ - FreeSchemaSetting__AccessControlBaseUrl=http://access-control-server:7000/api/
105
+ - JWTSettings__SecretKey=${JWT_SECRET}
106
+ - ApiSettings__ftp__ImageUploadApiUrl=${FTP_IMAGE_UPLOAD_API_URL}
107
+ - ApiSettings__ftp__FtpServerUrl=${FTP_SERVER_URL}
108
+ - ApiSettings__ftp__FtpUsername=${FTP_USERNAME}
109
+ - ApiSettings__ftp__FtpPassword=${FTP_PASSWORD}
110
+ - SmtpSettings__SmtpHost=${SMTP_HOST}
111
+ - SmtpSettings__SmtpUsername=${SMTP_USERNAME}
112
+ - SmtpSettings__SmtpPassword=${SMTP_PASSWORD}
113
+ - SmtpSettings__SmtpPort=${SMTP_PORT}
114
+ - SmtpSettings__FromAddress=${SMTP_FROM_ADDRESS}
115
+ - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Production}
116
+ - ASPNETCORE_URLS=http://+:7000
117
+ depends_on:
118
+ access-control-server:
119
+ condition: service_started
120
+ networks:
121
+ - freeschema-network
122
+ restart: unless-stopped
123
+ healthcheck:
124
+ test: ["CMD-SHELL", "curl -sI http://localhost:7000/health || exit 1"]
125
+ interval: 10s
126
+ retries: 5
127
+ start_period: 120s
128
+ timeout: 5s
129
+
130
+ node-server:
131
+ image: mentorayush/node-server:latest
132
+ container_name: ${CONTAINER_PREFIX:-}node-server
133
+ extra_hosts:
134
+ - "host.docker.internal:host-gateway"
135
+ env_file:
136
+ - .env
137
+ environment:
138
+ - BASE_URL=http://wico-server:7000/api
139
+ - PORT=5000
140
+ - MFTSCCS_BASE_URL=http://wico-server:7000
141
+ - MQTT_BROKER=${MQTT_HOST}
142
+ - MQTT_PORT=${MQTT_PORT}
143
+ - MQTT_USERNAME=${MQTT_USERNAME}
144
+ - MQTT_PASSWORD=${MQTT_PASSWORD}
145
+ - ACCESS_CONTROL_BASE_URL=http://access-control-server:7000/api
146
+ restart: unless-stopped
147
+ volumes:
148
+ - node_server_logs:/app/logs
149
+ depends_on:
150
+ access-control-server:
151
+ condition: service_started
152
+ wico-server:
153
+ condition: service_started
154
+ networks:
155
+ - freeschema-network
156
+ healthcheck:
157
+ test: ["CMD-SHELL", "curl -sI http://localhost:5000/health || exit 1"]
158
+ interval: 1m30s
159
+ timeout: 30s
160
+ retries: 5
161
+ start_period: 30s
162
+
163
+ node-cache-server:
164
+ image: mentorayush/node-cache-server:latest
165
+ container_name: ${CONTAINER_PREFIX:-}node-cache-server
166
+ extra_hosts:
167
+ - "host.docker.internal:host-gateway"
168
+ env_file:
169
+ - .env
170
+ environment:
171
+ - NODE_ENV=${NODE_ENV:-production}
172
+ - DISABLE_SWAGGER=${DISABLE_SWAGGER:-true}
173
+ - BASE_URL=http://wico-server:7000/api
174
+ - PORT=5000
175
+ - MFTSCCS_BASE_URL=http://wico-server:7000
176
+ - MQTT_BROKER=${MQTT_HOST}
177
+ - MQTT_PORT=${MQTT_PORT}
178
+ - MQTT_USERNAME=${MQTT_USERNAME}
179
+ - MQTT_PASSWORD=${MQTT_PASSWORD}
180
+ - ACCESS_CONTROL_BASE_URL=http://access-control-server:7000/api
181
+ restart: unless-stopped
182
+ depends_on:
183
+ wico-server:
184
+ condition: service_started
185
+ access-control-server:
186
+ condition: service_started
187
+ networks:
188
+ - freeschema-network
189
+
190
+ log-server:
191
+ image: mentorayush/log-server:latest
192
+ container_name: ${CONTAINER_PREFIX:-}log-server
193
+ env_file:
194
+ - .env
195
+ environment:
196
+ - MFTSCCS_BASE_URL=http://wico-server:7000
197
+ - LOGPATH=/app/logs
198
+ - PORT=5000
199
+ restart: unless-stopped
200
+ volumes:
201
+ - logs_data:/app/logs
202
+ - anomaly_data:/app/anomalyData
203
+ depends_on:
204
+ access-control-server:
205
+ condition: service_started
206
+ wico-server:
207
+ condition: service_started
208
+ networks:
209
+ - freeschema-network
210
+ healthcheck:
211
+ test: ["CMD-SHELL", "curl -sI http://localhost:5000/health || exit 1"]
212
+ interval: 1m30s
213
+ timeout: 30s
214
+ retries: 5
215
+ start_period: 30s
216
+
217
+ vccs-app:
218
+ image: mentorayush/vccs-app:latest
219
+ container_name: ${CONTAINER_PREFIX:-}vccs-app
220
+ env_file:
221
+ - .env.frontend
222
+ volumes:
223
+ - ./nginx/vccs-app.conf:/etc/nginx/conf.d/default.conf:ro
224
+ restart: unless-stopped
225
+ depends_on:
226
+ - wico-server
227
+ - node-server
228
+ networks:
229
+ - freeschema-network
230
+
231
+ wico-app:
232
+ image: mentorayush/wico-app:latest
233
+ container_name: ${CONTAINER_PREFIX:-}wico-app
234
+ env_file:
235
+ - .env.frontend
236
+ volumes:
237
+ - ./nginx/wico-app.conf:/etc/nginx/conf.d/default.conf:ro
238
+ restart: unless-stopped
239
+ depends_on:
240
+ - wico-server
241
+ - node-server
242
+ networks:
243
+ - freeschema-network
244
+
245
+ nginx-server:
246
+ image: nginx:alpine
247
+ container_name: ${CONTAINER_PREFIX:-}nginx-server
248
+ restart: unless-stopped
249
+ ports:
250
+ - "${NGINX_PORT:-80}:80"
251
+ environment:
252
+ - CORS_ORIGIN=${CORS_ORIGIN:-*}
253
+ volumes:
254
+ - ./nginx/nginx.conf.template:/etc/nginx/templates/default.conf.template:ro
255
+ depends_on:
256
+ - wico-app
257
+ - vccs-app
258
+ - node-server
259
+ - node-cache-server
260
+ - log-server
261
+ - wico-server
262
+ - access-control-server
263
+ networks:
264
+ - freeschema-network
265
+
266
+
267
+ networks:
268
+ freeschema-network:
269
+ driver: bridge
270
+
271
+ volumes:
272
+ mysql-data:
273
+ driver: local
274
+ logs_data:
275
+ driver: local
276
+ anomaly_data:
277
+ driver: local
278
+ node_server_logs:
279
+ driver: local
@@ -0,0 +1,11 @@
1
+ listener 1883
2
+ allow_anonymous false
3
+ password_file /mosquitto/config/password.txt
4
+
5
+ listener 9001
6
+ protocol websockets
7
+ allow_anonymous false
8
+
9
+ persistence true
10
+ persistence_location /mosquitto/data/
11
+ log_dest file /mosquitto/log/mosquitto.log
@@ -0,0 +1,54 @@
1
+ [mysqld]
2
+ bind-address = 0.0.0.0
3
+
4
+ # Connection and timeout settings
5
+ connect_timeout = 60
6
+ wait_timeout = 28800
7
+ interactive_timeout = 28800
8
+ net_read_timeout = 120
9
+ net_write_timeout = 120
10
+
11
+ # Connection limits
12
+ max_connections = 10000
13
+ max_connect_errors = 100000
14
+
15
+ # MyISAM Recovery
16
+ myisam-recover-options = BACKUP
17
+
18
+ # Replication Settings
19
+ server-id = 1
20
+ log_bin = mysql-bin
21
+ binlog_format = row
22
+ gtid_mode = ON
23
+ enforce-gtid-consistency = ON
24
+ log_replica_updates = ON
25
+ max_binlog_size = 500M
26
+
27
+ # InnoDB Performance
28
+ innodb_buffer_pool_size = 3G
29
+ innodb_log_buffer_size = 128M
30
+ innodb_redo_log_capacity = 2G
31
+ innodb_flush_log_at_trx_commit = 2
32
+
33
+ # Buffer Sizes
34
+ sort_buffer_size = 4M
35
+ join_buffer_size = 4M
36
+ read_buffer_size = 1M
37
+ read_rnd_buffer_size = 1M
38
+ tmp_table_size = 64M
39
+ max_heap_table_size = 64M
40
+
41
+ # Logging
42
+ log_error = /var/lib/mysql/error.log
43
+ slow_query_log = 1
44
+ slow_query_log_file = /var/lib/mysql/mysql-slow.log
45
+
46
+ # Character set
47
+ character-set-server = utf8mb4
48
+ collation-server = utf8mb4_unicode_ci
49
+
50
+ # SQL mode
51
+ sql_mode = "ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
52
+
53
+ expire_logs_days = 7
54
+ sync_binlog = 1
@@ -0,0 +1,330 @@
1
+ # ================================
2
+ # WebSocket connection upgrade map
3
+ # ================================
4
+ map $http_upgrade $connection_upgrade {
5
+ default upgrade;
6
+ '' close;
7
+ }
8
+
9
+ # ================================
10
+ # Route /images/ & /icons/ to the correct frontend app based on Referer
11
+ # ================================
12
+ map $http_referer $assets_backend {
13
+ ~*/vccs/ vccs-app;
14
+ default wico-app;
15
+ }
16
+
17
+ # ================================
18
+ # Main server — HTTP only (SSL handled by external reverse proxy)
19
+ # ================================
20
+ server {
21
+ listen 80;
22
+ server_name _;
23
+
24
+ # ── Security Headers ─────────────────────────────────────
25
+ add_header X-Frame-Options "SAMEORIGIN" always;
26
+ add_header X-Content-Type-Options "nosniff" always;
27
+ add_header X-XSS-Protection "1; mode=block" always;
28
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
29
+
30
+ # ── Hide Upstream CORS Header ─────────────────────────────────────
31
+ proxy_hide_header Access-Control-Allow-Origin;
32
+
33
+ # ── General Settings ─────────────────────────────────────
34
+ client_max_body_size 50M;
35
+
36
+ # ── Docker DNS (required for variable-based proxy_pass) ─
37
+ resolver 127.0.0.11 valid=30s;
38
+
39
+ # ── Gzip Compression ─────────────────────────────────────
40
+ gzip on;
41
+ gzip_vary on;
42
+ gzip_proxied any;
43
+ gzip_comp_level 6;
44
+ gzip_min_length 256;
45
+ gzip_types
46
+ text/plain
47
+ text/css
48
+ text/javascript
49
+ application/javascript
50
+ application/json
51
+ application/xml
52
+ image/svg+xml;
53
+
54
+ # -----------------------------
55
+ # Health Check (IMPORTANT for HA)
56
+ # -----------------------------
57
+ location /health {
58
+ return 200 "OK";
59
+ add_header Content-Type text/plain;
60
+ }
61
+
62
+ # ================================
63
+ # FRONTEND APPS
64
+ # ================================
65
+
66
+ location ^~ /images/ {
67
+ proxy_pass http://$assets_backend:80;
68
+ proxy_set_header Host $host;
69
+ proxy_set_header X-Real-IP $remote_addr;
70
+ }
71
+
72
+ location ^~ /icons/ {
73
+ proxy_pass http://$assets_backend:80;
74
+ proxy_set_header Host $host;
75
+ proxy_set_header X-Real-IP $remote_addr;
76
+ }
77
+
78
+ location ^~ /vccs/ {
79
+ proxy_pass http://vccs-app:80/;
80
+ proxy_set_header Host $host;
81
+ proxy_set_header X-Real-IP $remote_addr;
82
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
83
+ proxy_set_header X-Forwarded-Proto $scheme;
84
+ proxy_http_version 1.1;
85
+ proxy_set_header Upgrade $http_upgrade;
86
+ proxy_set_header Connection $connection_upgrade;
87
+ }
88
+
89
+ # ================================
90
+ # API ROUTING
91
+ # ================================
92
+
93
+ location /socket {
94
+ proxy_pass http://node-server:5000;
95
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
96
+ proxy_set_header X-Real-IP $remote_addr;
97
+ proxy_http_version 1.1;
98
+ proxy_read_timeout 86400;
99
+ proxy_set_header Upgrade $http_upgrade;
100
+ proxy_set_header Connection "upgrade";
101
+ }
102
+
103
+ location /api/v1 {
104
+ if ($request_method = OPTIONS) {
105
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
106
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
107
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
108
+ add_header 'Access-Control-Max-Age' 86400 always;
109
+ return 204;
110
+ }
111
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
112
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
113
+ proxy_pass http://node-server:5000;
114
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
115
+ proxy_set_header X-Real-IP $remote_addr;
116
+ proxy_set_header Host $host;
117
+ proxy_set_header X-Forwarded-Host $host;
118
+ proxy_set_header X-Forwarded-Proto $scheme;
119
+ }
120
+
121
+ location /webhook {
122
+ if ($request_method = OPTIONS) {
123
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
124
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
125
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
126
+ add_header 'Access-Control-Max-Age' 86400 always;
127
+ return 204;
128
+ }
129
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
130
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
131
+ proxy_pass http://node-server:5000;
132
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
133
+ proxy_set_header X-Real-IP $remote_addr;
134
+ proxy_set_header Host $host;
135
+ proxy_set_header X-Forwarded-Host $host;
136
+ proxy_set_header X-Forwarded-Proto $scheme;
137
+ }
138
+
139
+ location /api {
140
+ if ($request_method = OPTIONS) {
141
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
142
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
143
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
144
+ add_header 'Access-Control-Max-Age' 86400 always;
145
+ return 204;
146
+ }
147
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
148
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
149
+ proxy_pass http://wico-server:7000;
150
+ proxy_set_header X-Real-IP $remote_addr;
151
+ proxy_set_header Host $host;
152
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
153
+ proxy_set_header X-Forwarded-Proto $scheme;
154
+ }
155
+
156
+ # ================================
157
+ # WICO-API PREFIX ROUTING
158
+ # ================================
159
+
160
+ location /wico-api/socket {
161
+ proxy_pass http://node-server:5000/socket;
162
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
163
+ proxy_set_header X-Real-IP $remote_addr;
164
+ proxy_http_version 1.1;
165
+ proxy_read_timeout 86400;
166
+ proxy_set_header Upgrade $http_upgrade;
167
+ proxy_set_header Connection "upgrade";
168
+ }
169
+
170
+ location /wico-api/api/v1 {
171
+ if ($request_method = OPTIONS) {
172
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
173
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
174
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
175
+ add_header 'Access-Control-Max-Age' 86400 always;
176
+ return 204;
177
+ }
178
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
179
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
180
+ proxy_pass http://node-server:5000/api/v1;
181
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
182
+ proxy_set_header X-Real-IP $remote_addr;
183
+ proxy_set_header Host $host;
184
+ proxy_set_header X-Forwarded-Host $host;
185
+ proxy_set_header X-Forwarded-Proto $scheme;
186
+ }
187
+
188
+ location /wico-api/webhook {
189
+ if ($request_method = OPTIONS) {
190
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
191
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
192
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
193
+ add_header 'Access-Control-Max-Age' 86400 always;
194
+ return 204;
195
+ }
196
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
197
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
198
+ proxy_pass http://node-server:5000/webhook;
199
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
200
+ proxy_set_header X-Real-IP $remote_addr;
201
+ proxy_set_header Host $host;
202
+ proxy_set_header X-Forwarded-Host $host;
203
+ proxy_set_header X-Forwarded-Proto $scheme;
204
+ }
205
+
206
+ location /wico-api/api {
207
+ if ($request_method = OPTIONS) {
208
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
209
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
210
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
211
+ add_header 'Access-Control-Max-Age' 86400 always;
212
+ return 204;
213
+ }
214
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
215
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
216
+ proxy_pass http://wico-server:7000/api;
217
+ proxy_set_header X-Real-IP $remote_addr;
218
+ proxy_set_header Host $host;
219
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
220
+ proxy_set_header X-Forwarded-Proto $scheme;
221
+ }
222
+
223
+ # ================================
224
+ # SERVICE-SPECIFIC PREFIX ROUTES
225
+ # ================================
226
+
227
+ location /access-control-api/ {
228
+ if ($request_method = OPTIONS) {
229
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
230
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
231
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
232
+ add_header 'Access-Control-Max-Age' 86400 always;
233
+ return 204;
234
+ }
235
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
236
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
237
+ proxy_pass http://access-control-server:7000/;
238
+ proxy_set_header Host $host;
239
+ proxy_set_header X-Real-IP $remote_addr;
240
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
241
+ proxy_set_header X-Forwarded-Proto $scheme;
242
+ }
243
+
244
+ location /node-api/ {
245
+ if ($request_method = OPTIONS) {
246
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
247
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
248
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
249
+ add_header 'Access-Control-Max-Age' 86400 always;
250
+ return 204;
251
+ }
252
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
253
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
254
+ proxy_pass http://node-server:5000/;
255
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
256
+ proxy_set_header X-Real-IP $remote_addr;
257
+ proxy_set_header Host $host;
258
+ proxy_set_header X-Forwarded-Host $host;
259
+ proxy_set_header X-Forwarded-Proto $scheme;
260
+ }
261
+
262
+ location /wico-api/ {
263
+ if ($request_method = OPTIONS) {
264
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
265
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
266
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
267
+ add_header 'Access-Control-Max-Age' 86400 always;
268
+ return 204;
269
+ }
270
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
271
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
272
+ proxy_pass http://wico-server:7000/;
273
+ proxy_set_header X-Forwarded-For $remote_addr;
274
+ proxy_set_header Host $host;
275
+ proxy_set_header X-Forwarded-Host $host;
276
+ proxy_set_header X-Real-IP $remote_addr;
277
+ proxy_set_header X-Forwarded-Proto $scheme;
278
+ }
279
+
280
+ location /cache-api/ {
281
+ if ($request_method = OPTIONS) {
282
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
283
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
284
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
285
+ add_header 'Access-Control-Max-Age' 86400 always;
286
+ return 204;
287
+ }
288
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
289
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
290
+ proxy_pass http://node-cache-server:5000/;
291
+ proxy_set_header Host $host;
292
+ proxy_set_header X-Real-IP $remote_addr;
293
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
294
+ proxy_set_header X-Forwarded-Proto $scheme;
295
+ }
296
+
297
+ location /log-api/ {
298
+ if ($request_method = OPTIONS) {
299
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
300
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
301
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Session-Id' always;
302
+ add_header 'Access-Control-Max-Age' 86400 always;
303
+ return 204;
304
+ }
305
+ add_header 'Access-Control-Allow-Origin' '${CORS_ORIGIN}' always;
306
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always;
307
+ proxy_pass http://log-server:5000/;
308
+ proxy_set_header Host $host;
309
+ proxy_set_header X-Real-IP $remote_addr;
310
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
311
+ proxy_set_header X-Forwarded-Proto $scheme;
312
+ proxy_http_version 1.1;
313
+ proxy_set_header Upgrade $http_upgrade;
314
+ proxy_set_header Connection $connection_upgrade;
315
+ }
316
+
317
+ # ================================
318
+ # WICO APP — Main domain (catch-all)
319
+ # ================================
320
+ location / {
321
+ proxy_pass http://wico-app:80;
322
+ proxy_set_header Host $host;
323
+ proxy_set_header X-Real-IP $remote_addr;
324
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
325
+ proxy_set_header X-Forwarded-Proto $scheme;
326
+ proxy_http_version 1.1;
327
+ proxy_set_header Upgrade $http_upgrade;
328
+ proxy_set_header Connection $connection_upgrade;
329
+ }
330
+ }
@@ -0,0 +1,21 @@
1
+ server {
2
+ listen 80;
3
+ server_name _;
4
+
5
+ root /usr/share/nginx/html;
6
+ index index.html;
7
+
8
+ location / {
9
+ try_files $uri /index.html;
10
+ }
11
+
12
+ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
13
+ expires 1y;
14
+ add_header Cache-Control "public, immutable";
15
+ }
16
+
17
+ gzip on;
18
+ gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
19
+
20
+ client_max_body_size 10M;
21
+ }
@@ -0,0 +1,21 @@
1
+ server {
2
+ listen 80;
3
+ server_name _;
4
+
5
+ root /usr/share/nginx/html;
6
+ index index.html;
7
+
8
+ location / {
9
+ try_files $uri /index.html;
10
+ }
11
+
12
+ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
13
+ expires 1y;
14
+ add_header Cache-Control "public, immutable";
15
+ }
16
+
17
+ gzip on;
18
+ gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
19
+
20
+ client_max_body_size 10M;
21
+ }