Skip to content

Commit 77ff4b7

Browse files
committed
feat: add support for CHouse UI in Docker service and UI
1 parent fd639a9 commit 77ff4b7

File tree

5 files changed

+96
-0
lines changed

5 files changed

+96
-0
lines changed

projects/api/src/server/common/services/docker.service.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { getAdminer } from "../../modules/container/types/service/adminer/compos
2424
import { getDirectus } from "../../modules/container/types/service/directus/compose";
2525
import { getMongoExpress } from "../../modules/container/types/service/mongo-express/compose";
2626
import { getPlausible } from "../../modules/container/types/service/plausible/compose";
27+
import { getChouseUi } from "../../modules/container/types/service/chouse-ui/compose";
2728
import { getClickhouseUi } from "../../modules/container/types/service/clickhouse-ui/compose";
2829
import { getRedisUi } from "../../modules/container/types/service/redis-ui/compose";
2930
import { getRocketAdmin } from "../../modules/container/types/service/rocketadmin/compose";
@@ -122,6 +123,34 @@ export class DockerService {
122123
case ServiceType.ADMINER:
123124
compose = await getAdminer(container);
124125
break;
126+
case ServiceType.CHOUSE_UI:
127+
if (!container.env) {
128+
const jwtSecret = randomBytes(32).toString('hex');
129+
const encryptionKey = randomBytes(32).toString('hex');
130+
131+
container.env = `
132+
# Core Settings
133+
PORT=5521
134+
NODE_ENV=production
135+
136+
# Authentication & Security
137+
JWT_SECRET=${jwtSecret}
138+
RBAC_ENCRYPTION_KEY=${encryptionKey}
139+
RBAC_ADMIN_PASSWORD=admin123!
140+
141+
# Database (SQLite by default)
142+
RBAC_DB_TYPE=sqlite
143+
RBAC_SQLITE_PATH=/app/data/rbac.db
144+
145+
# For PostgreSQL, uncomment and configure:
146+
# RBAC_DB_TYPE=postgres
147+
# RBAC_POSTGRES_URL=postgres://user:password@host:5432/dbname
148+
`;
149+
await this.containerService.updateForce(container.id, { env: container.env });
150+
await this.createEnvFile(container);
151+
}
152+
compose = await getChouseUi(container);
153+
break;
125154
case ServiceType.CLICKHOUSE_UI:
126155
if (!container.env) {
127156
container.env = `

projects/api/src/server/modules/container/enums/all-container-types.enum.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {registerEnumType} from '@nestjs/graphql';
22

33
export enum AllContainerTypes {
44
ADMINER = 'ADMINER',
5+
CHOUSE_UI = 'CHOUSE_UI',
56
CLICKHOUSE_UI = 'CLICKHOUSE_UI',
67
CUSTOM = 'CUSTOM',
78
DIRECTUS = 'DIRECTUS',

projects/api/src/server/modules/container/enums/service-type.enum.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {registerEnumType} from '@nestjs/graphql';
22

33
export enum ServiceType {
44
ADMINER = 'ADMINER',
5+
CHOUSE_UI = 'CHOUSE_UI',
56
CLICKHOUSE_UI = 'CLICKHOUSE_UI',
67
CUSTOM = 'CUSTOM',
78
DIRECTUS = 'DIRECTUS',
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import {Container} from '../../../container.model';
2+
import {execa} from 'execa';
3+
4+
export async function getChouseUi(container: Container): Promise<string> {
5+
const basicAuth = !!(container?.basicAuth?.username && container?.basicAuth?.pw);
6+
const additionalLabels = [];
7+
const middlewares = ['secure-headers@swarm'];
8+
9+
if (basicAuth) {
10+
const {stdout: creds} = await execa(
11+
`echo $(htpasswd -nb ${container.basicAuth.username} ${container.basicAuth.pw})`,
12+
{shell: true}
13+
);
14+
additionalLabels.push(` - traefik.http.middlewares.${container.id}-auth.basicauth.users=${creds.replace(/\$/gi, '$$$')}`);
15+
middlewares.unshift(`${container.id}-auth`);
16+
}
17+
18+
return `
19+
networks:
20+
traefik-public:
21+
external: true
22+
deploy-party:
23+
external: true
24+
25+
services:
26+
chouse-ui:
27+
image: ghcr.io/daun-gatal/chouse-ui:${container.buildImage || 'latest'}
28+
labels:
29+
- deploy.party.id=${container.id}
30+
env_file:
31+
- .env
32+
networks:
33+
- traefik-public
34+
- deploy-party
35+
deploy:
36+
update_config:
37+
order: start-first
38+
failure_action: rollback
39+
delay: 10s
40+
rollback_config:
41+
parallelism: 0
42+
order: stop-first
43+
restart_policy:
44+
condition: any
45+
delay: 5s
46+
max_attempts: 3
47+
window: 120s
48+
labels:
49+
- traefik.enable=true
50+
- traefik.docker.network=traefik-public
51+
- traefik.constraint-label=traefik-public
52+
- traefik.http.routers.${container.id}-app-http.rule=Host(\`${container.url}\`) || Host(\`www.${container.url}\`)
53+
- traefik.http.routers.${container.id}-app-http.entrypoints=http
54+
- traefik.http.routers.${container.id}-app-http.middlewares=https-redirect@swarm
55+
- traefik.http.routers.${container.id}-app-https.rule=Host(\`${container.url}\`) || Host(\`www.${container.url}\`)
56+
- traefik.http.routers.${container.id}-app-https.entrypoints=https
57+
- traefik.http.routers.${container.id}-app-https.tls=true
58+
- traefik.http.routers.${container.id}-app-https.tls.certresolver=le
59+
${additionalLabels.join('\n')}
60+
- traefik.http.routers.${container.id}-app-https.middlewares=${middlewares.join(',')}
61+
- traefik.http.middlewares.${container.id}-redirect.redirectregex.permanent=true
62+
- traefik.http.services.${container.id}-app.loadbalancer.server.port=5521
63+
`;
64+
}

projects/app/src/components/ServiceForm.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const props = defineProps<{
1414
1515
const typeOptions = [
1616
{ label: 'Adminer', value: 'ADMINER' },
17+
{ label: 'CHouse UI', value: 'CHOUSE_UI' },
1718
{ label: 'ClickHouse UI', value: 'CLICKHOUSE_UI' },
1819
{ label: 'Custom', value: 'CUSTOM' },
1920
{ label: 'Directus', value: 'DIRECTUS' },

0 commit comments

Comments
 (0)