create-rykira-app 1.0.2 → 2.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.
- package/bin/cli.js +4 -55
- package/package.json +1 -1
- package/template/README.md +4 -32
- package/template/apps/admin/nixpacks.toml +1 -1
- package/template/apps/web/nixpacks.toml +1 -1
- package/template/docker-compose.yml +19 -0
- package/template/package.json +1 -2
- package/template/.github/workflows/ci-cd.yml +0 -97
- package/template/infrastructure/docker/Dockerfile.admin +0 -36
- package/template/infrastructure/docker/Dockerfile.api +0 -36
- package/template/infrastructure/docker/Dockerfile.web +0 -48
- package/template/infrastructure/docker/compose.dev.yml +0 -52
- package/template/infrastructure/docker/compose.prod.yml +0 -166
- package/template/infrastructure/scripts/deploy.sh +0 -49
- package/template/infrastructure/scripts/dev.sh +0 -5
- package/template/infrastructure/scripts/init-traefik.sh +0 -10
- package/template/infrastructure/scripts/setup-server.sh +0 -50
- package/template/infrastructure/scripts/update.sh +0 -7
- package/template/infrastructure/traefik/acme.json +0 -0
- package/template/infrastructure/traefik/dynamic.yml +0 -23
- package/template/infrastructure/traefik/traefik.yml +0 -31
package/bin/cli.js
CHANGED
|
@@ -75,24 +75,6 @@ program
|
|
|
75
75
|
name: 'includeApi',
|
|
76
76
|
message: 'Include Express API?',
|
|
77
77
|
default: true,
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
type: 'list',
|
|
81
|
-
name: 'deploymentStrategy',
|
|
82
|
-
message: 'Choose your deployment strategy:',
|
|
83
|
-
choices: [
|
|
84
|
-
{ name: 'Automated CI/CD (GitHub Actions + GHCR)', value: 'cicd' },
|
|
85
|
-
{ name: 'Coolify (Self-Hosted PaaS)', value: 'coolify' },
|
|
86
|
-
{ name: 'Direct Source Build (Simple)', value: 'direct' }
|
|
87
|
-
],
|
|
88
|
-
default: 'cicd'
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
type: 'input',
|
|
92
|
-
name: 'githubUsername',
|
|
93
|
-
message: 'GitHub Username (required for GHCR image tagging):',
|
|
94
|
-
when: (answers) => answers.deploymentStrategy === 'cicd',
|
|
95
|
-
validate: (input) => input.length > 0 ? true : 'GitHub username is required for CI/CD setup'
|
|
96
78
|
}
|
|
97
79
|
]);
|
|
98
80
|
|
|
@@ -126,7 +108,6 @@ program
|
|
|
126
108
|
if (!promptAnswers.includeAdmin) {
|
|
127
109
|
spinner.text = 'Removing Admin Panel...';
|
|
128
110
|
await fs.remove(path.join(rootDir, 'apps/admin'));
|
|
129
|
-
await fs.remove(path.join(rootDir, 'infrastructure/docker/Dockerfile.admin'));
|
|
130
111
|
// Note: You might need to clean up pnpm-workspace.yaml or turbo.json if strict
|
|
131
112
|
}
|
|
132
113
|
|
|
@@ -134,17 +115,13 @@ program
|
|
|
134
115
|
if (!promptAnswers.includeApi) {
|
|
135
116
|
spinner.text = 'Removing Express API...';
|
|
136
117
|
await fs.remove(path.join(rootDir, 'apps/api'));
|
|
137
|
-
await fs.remove(path.join(rootDir, 'infrastructure/docker/Dockerfile.api'));
|
|
138
118
|
}
|
|
139
119
|
|
|
140
|
-
// Deployment Variables
|
|
141
|
-
const
|
|
142
|
-
const isCoolify = promptAnswers.deploymentStrategy === 'coolify';
|
|
143
|
-
const isDirect = promptAnswers.deploymentStrategy === 'direct';
|
|
120
|
+
// Deployment Variables (Forced to Coolify)
|
|
121
|
+
const isCoolify = true;
|
|
144
122
|
|
|
145
123
|
// Update Compose files with project name and deployment logic
|
|
146
|
-
const
|
|
147
|
-
const composeDevPath = path.join(rootDir, 'infrastructure/docker/compose.dev.yml');
|
|
124
|
+
const composeDevPath = path.join(rootDir, 'docker-compose.yml');
|
|
148
125
|
|
|
149
126
|
const updateFileWithContext = async (filePath) => {
|
|
150
127
|
if (fs.existsSync(filePath)) {
|
|
@@ -152,37 +129,21 @@ program
|
|
|
152
129
|
const compiledTemplate = Handlebars.compile(content);
|
|
153
130
|
const compiledResult = compiledTemplate({
|
|
154
131
|
projectName: path.basename(rootDir),
|
|
155
|
-
githubUsername: promptAnswers.githubUsername,
|
|
156
|
-
isCicd,
|
|
157
132
|
isCoolify,
|
|
158
|
-
isDirect,
|
|
159
133
|
includeAdmin: promptAnswers.includeAdmin,
|
|
160
134
|
includeApi: promptAnswers.includeApi,
|
|
161
|
-
deploymentStrategy:
|
|
135
|
+
deploymentStrategy: 'coolify'
|
|
162
136
|
});
|
|
163
137
|
await fs.writeFile(filePath, compiledResult);
|
|
164
138
|
}
|
|
165
139
|
};
|
|
166
140
|
|
|
167
|
-
await updateFileWithContext(composeProdPath);
|
|
168
141
|
await updateFileWithContext(composeDevPath);
|
|
169
142
|
|
|
170
|
-
// Update Deploy Script
|
|
171
|
-
const deployScriptPath = path.join(rootDir, 'infrastructure/scripts/deploy.sh');
|
|
172
|
-
await updateFileWithContext(deployScriptPath);
|
|
173
|
-
|
|
174
143
|
// Update README.md
|
|
175
144
|
const readmePath = path.join(rootDir, 'README.md');
|
|
176
145
|
await updateFileWithContext(readmePath);
|
|
177
146
|
|
|
178
|
-
// Cleanup
|
|
179
|
-
if (!isCicd) {
|
|
180
|
-
// Remove CI/CD workflows if not using CI/CD
|
|
181
|
-
// Note: If you want to keep CI (tests) for other modes, you might want to split the file or keep a basic one.
|
|
182
|
-
// For now, removing the specific ci-cd pipeline.
|
|
183
|
-
await fs.remove(path.join(rootDir, '.github/workflows/ci-cd.yml'));
|
|
184
|
-
}
|
|
185
|
-
|
|
186
147
|
spinner.succeed(chalk.green('Project created successfully!'));
|
|
187
148
|
|
|
188
149
|
console.log('\nNext steps:');
|
|
@@ -190,18 +151,6 @@ program
|
|
|
190
151
|
console.log(chalk.cyan(' pnpm install'));
|
|
191
152
|
console.log(chalk.cyan(' cp .env.example .env'));
|
|
192
153
|
console.log(chalk.cyan(' pnpm dev'));
|
|
193
|
-
|
|
194
|
-
if (isCicd) {
|
|
195
|
-
console.log(chalk.yellow('\nCI/CD Setup:'));
|
|
196
|
-
console.log(' 1. Create a repository on GitHub');
|
|
197
|
-
console.log(' 2. Add secrets: HOST, USERNAME, SSH_KEY');
|
|
198
|
-
console.log(' 3. Push to main to trigger deployment');
|
|
199
|
-
} else if (isDirect) {
|
|
200
|
-
console.log(chalk.yellow('\nDeployment:'));
|
|
201
|
-
console.log(' 1. Setup your server using infrastructure/scripts/setup-server.sh');
|
|
202
|
-
console.log(' 2. Configure .env with DEPLOY_HOST details');
|
|
203
|
-
console.log(' 3. Run: npm run deploy');
|
|
204
|
-
}
|
|
205
154
|
|
|
206
155
|
} catch (error) {
|
|
207
156
|
spinner.fail(chalk.red('Failed to create project'));
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -16,42 +16,14 @@ This is a Next.js monorepo template with shadcn/ui.
|
|
|
16
16
|
|
|
17
17
|
## Deployment
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
This project is configured to be deployed easily using [Coolify](https://coolify.io/).
|
|
20
20
|
|
|
21
|
-
To deploy your application:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
pnpm run deploy
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
{{#if isCicd}}
|
|
28
|
-
### Automated CI/CD Setup
|
|
29
|
-
1. Push this repository to GitHub.
|
|
30
|
-
2. Go to Settings > Secrets and Variables > Actions.
|
|
31
|
-
3. Add the following secrets:
|
|
32
|
-
- `HOST`: Your server IP address.
|
|
33
|
-
- `USERNAME`: Your server SSH username (e.g., `root`).
|
|
34
|
-
- `SSH_KEY`: Your private SSH key.
|
|
35
|
-
4. Push to `main` to trigger deployment.
|
|
36
|
-
{{/if}}
|
|
37
|
-
|
|
38
|
-
{{#if isDirect}}
|
|
39
|
-
### Direct Source Build Setup
|
|
40
|
-
1. SSH into your server.
|
|
41
|
-
2. Run the setup script:
|
|
42
|
-
```bash
|
|
43
|
-
curl -sL https://raw.githubusercontent.com/user/repo/main/infrastructure/scripts/setup-server.sh | bash
|
|
44
|
-
```
|
|
45
|
-
3. Configure your `.env` file with `DEPLOY_HOST` and `DEPLOY_USER`.
|
|
46
|
-
4. Run `pnpm run deploy` from your local machine.
|
|
47
|
-
{{/if}}
|
|
48
|
-
|
|
49
|
-
{{#if isCoolify}}
|
|
50
21
|
### Coolify Setup
|
|
51
22
|
1. Create a project in your Coolify dashboard.
|
|
52
23
|
2. Connect this Git repository.
|
|
53
|
-
3.
|
|
54
|
-
|
|
24
|
+
3. Add a resource for each application (`web`, `admin`, `api`).
|
|
25
|
+
4. Set the Base Directory to `/` (root) for all of them.
|
|
26
|
+
5. Set the respective build and start commands for each app (e.g. `pnpm install && pnpm turbo build --filter=web...` and `pnpm --filter web start`).
|
|
55
27
|
|
|
56
28
|
## Adding components
|
|
57
29
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
version: "3.9"
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
|
|
5
|
+
postgres:
|
|
6
|
+
image: postgres:16
|
|
7
|
+
container_name: {{projectName}}-postgres-dev
|
|
8
|
+
environment:
|
|
9
|
+
POSTGRES_DB: ${POSTGRES_DB}
|
|
10
|
+
POSTGRES_USER: ${POSTGRES_USER}
|
|
11
|
+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
12
|
+
ports:
|
|
13
|
+
- "5432:5432"
|
|
14
|
+
|
|
15
|
+
redis:
|
|
16
|
+
image: redis:7
|
|
17
|
+
container_name: {{projectName}}-redis-dev
|
|
18
|
+
ports:
|
|
19
|
+
- "6379:6379"
|
package/template/package.json
CHANGED
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
"start": "turbo start",
|
|
9
9
|
"lint": "turbo lint",
|
|
10
10
|
"format": "turbo format",
|
|
11
|
-
"typecheck": "turbo typecheck"
|
|
12
|
-
"deploy": "./infrastructure/scripts/deploy.sh"
|
|
11
|
+
"typecheck": "turbo typecheck"
|
|
13
12
|
},
|
|
14
13
|
"devDependencies": {
|
|
15
14
|
"@workspace/eslint-config": "workspace:*",
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
name: CI/CD Pipeline
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ "main" ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ "main" ]
|
|
8
|
-
|
|
9
|
-
env:
|
|
10
|
-
REGISTRY: ghcr.io
|
|
11
|
-
IMAGE_NAME: ${{ github.repository }}
|
|
12
|
-
|
|
13
|
-
jobs:
|
|
14
|
-
test:
|
|
15
|
-
name: Build, Lint, and Test
|
|
16
|
-
runs-on: ubuntu-latest
|
|
17
|
-
steps:
|
|
18
|
-
- uses: actions/checkout@v4
|
|
19
|
-
with:
|
|
20
|
-
fetch-depth: 2
|
|
21
|
-
|
|
22
|
-
- uses: pnpm/action-setup@v3
|
|
23
|
-
with:
|
|
24
|
-
version: 9
|
|
25
|
-
|
|
26
|
-
- uses: actions/setup-node@v4
|
|
27
|
-
with:
|
|
28
|
-
node-version: 20
|
|
29
|
-
cache: 'pnpm'
|
|
30
|
-
|
|
31
|
-
- name: Install dependencies
|
|
32
|
-
run: pnpm install
|
|
33
|
-
|
|
34
|
-
- name: Build
|
|
35
|
-
run: pnpm build
|
|
36
|
-
|
|
37
|
-
- name: Lint
|
|
38
|
-
run: pnpm lint
|
|
39
|
-
|
|
40
|
-
- name: Typecheck
|
|
41
|
-
run: pnpm typecheck
|
|
42
|
-
|
|
43
|
-
build-and-push:
|
|
44
|
-
needs: test
|
|
45
|
-
runs-on: ubuntu-latest
|
|
46
|
-
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
47
|
-
permissions:
|
|
48
|
-
contents: read
|
|
49
|
-
packages: write
|
|
50
|
-
strategy:
|
|
51
|
-
matrix:
|
|
52
|
-
service: [web, admin, api]
|
|
53
|
-
steps:
|
|
54
|
-
- uses: actions/checkout@v4
|
|
55
|
-
|
|
56
|
-
- name: Log in to the Container registry
|
|
57
|
-
uses: docker/login-action@v3
|
|
58
|
-
with:
|
|
59
|
-
registry: ${{ env.REGISTRY }}
|
|
60
|
-
username: ${{ github.actor }}
|
|
61
|
-
password: ${{ secrets.GITHUB_TOKEN }}
|
|
62
|
-
|
|
63
|
-
- name: Extract metadata (tags, labels) for Docker
|
|
64
|
-
id: meta
|
|
65
|
-
uses: docker/metadata-action@v5
|
|
66
|
-
with:
|
|
67
|
-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-${{ matrix.service }}
|
|
68
|
-
tags: |
|
|
69
|
-
type=raw,value=latest
|
|
70
|
-
type=sha,prefix=
|
|
71
|
-
|
|
72
|
-
- name: Build and push Docker image
|
|
73
|
-
uses: docker/build-push-action@v5
|
|
74
|
-
with:
|
|
75
|
-
context: .
|
|
76
|
-
file: infrastructure/docker/Dockerfile.${{ matrix.service }}
|
|
77
|
-
push: true
|
|
78
|
-
tags: ${{ steps.meta.outputs.tags }}
|
|
79
|
-
labels: ${{ steps.meta.outputs.labels }}
|
|
80
|
-
|
|
81
|
-
deploy:
|
|
82
|
-
needs: build-and-push
|
|
83
|
-
runs-on: ubuntu-latest
|
|
84
|
-
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
85
|
-
steps:
|
|
86
|
-
- name: Deploy to VPS
|
|
87
|
-
uses: appleboy/ssh-action@v1.0.3
|
|
88
|
-
with:
|
|
89
|
-
host: ${{ secrets.HOST }}
|
|
90
|
-
username: ${{ secrets.USERNAME }}
|
|
91
|
-
key: ${{ secrets.SSH_KEY }}
|
|
92
|
-
script: |
|
|
93
|
-
cd ~/app || exit
|
|
94
|
-
# Pull latest images
|
|
95
|
-
docker compose -f infrastructure/docker/compose.prod.yml pull
|
|
96
|
-
# Restart containers
|
|
97
|
-
docker compose -f infrastructure/docker/compose.prod.yml up -d
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
FROM node:20-alpine AS base
|
|
2
|
-
|
|
3
|
-
WORKDIR /app
|
|
4
|
-
RUN corepack enable
|
|
5
|
-
|
|
6
|
-
FROM base AS pruner
|
|
7
|
-
|
|
8
|
-
COPY . .
|
|
9
|
-
|
|
10
|
-
RUN pnpm dlx turbo prune admin --docker
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
FROM base AS installer
|
|
14
|
-
|
|
15
|
-
WORKDIR /app
|
|
16
|
-
|
|
17
|
-
COPY --from=pruner /app/out/json/ .
|
|
18
|
-
|
|
19
|
-
RUN pnpm install --frozen-lockfile
|
|
20
|
-
|
|
21
|
-
COPY --from=pruner /app/out/full/ .
|
|
22
|
-
|
|
23
|
-
RUN pnpm turbo build --filter=admin
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
FROM base AS runner
|
|
27
|
-
|
|
28
|
-
WORKDIR /app
|
|
29
|
-
|
|
30
|
-
ENV NODE_ENV=production
|
|
31
|
-
|
|
32
|
-
COPY --from=installer /app .
|
|
33
|
-
|
|
34
|
-
EXPOSE 3001
|
|
35
|
-
|
|
36
|
-
CMD ["pnpm", "start:admin"]
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
FROM node:20-alpine AS base
|
|
2
|
-
|
|
3
|
-
WORKDIR /app
|
|
4
|
-
RUN corepack enable
|
|
5
|
-
|
|
6
|
-
FROM base AS pruner
|
|
7
|
-
|
|
8
|
-
COPY . .
|
|
9
|
-
|
|
10
|
-
RUN pnpm dlx turbo prune api --docker
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
FROM base AS installer
|
|
14
|
-
|
|
15
|
-
WORKDIR /app
|
|
16
|
-
|
|
17
|
-
COPY --from=pruner /app/out/json/ .
|
|
18
|
-
|
|
19
|
-
RUN pnpm install --frozen-lockfile
|
|
20
|
-
|
|
21
|
-
COPY --from=pruner /app/out/full/ .
|
|
22
|
-
|
|
23
|
-
RUN pnpm turbo build --filter=api
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
FROM base AS runner
|
|
27
|
-
|
|
28
|
-
WORKDIR /app
|
|
29
|
-
|
|
30
|
-
ENV NODE_ENV=production
|
|
31
|
-
|
|
32
|
-
COPY --from=installer /app .
|
|
33
|
-
|
|
34
|
-
EXPOSE 4000
|
|
35
|
-
|
|
36
|
-
CMD ["node", "apps/api/dist/index.js"]
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
FROM node:20-alpine AS base
|
|
2
|
-
|
|
3
|
-
WORKDIR /app
|
|
4
|
-
RUN corepack enable
|
|
5
|
-
|
|
6
|
-
# -----------------------------
|
|
7
|
-
# 1️⃣ PRUNE MONOREPO
|
|
8
|
-
# -----------------------------
|
|
9
|
-
|
|
10
|
-
FROM base AS pruner
|
|
11
|
-
|
|
12
|
-
COPY . .
|
|
13
|
-
|
|
14
|
-
RUN pnpm dlx turbo prune web --docker
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# -----------------------------
|
|
18
|
-
# 2️⃣ INSTALL + BUILD
|
|
19
|
-
# -----------------------------
|
|
20
|
-
|
|
21
|
-
FROM base AS installer
|
|
22
|
-
|
|
23
|
-
WORKDIR /app
|
|
24
|
-
|
|
25
|
-
COPY --from=pruner /app/out/json/ .
|
|
26
|
-
|
|
27
|
-
RUN pnpm install --frozen-lockfile
|
|
28
|
-
|
|
29
|
-
COPY --from=pruner /app/out/full/ .
|
|
30
|
-
|
|
31
|
-
RUN pnpm turbo build --filter=web
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
# -----------------------------
|
|
35
|
-
# 3️⃣ RUN APPLICATION
|
|
36
|
-
# -----------------------------
|
|
37
|
-
|
|
38
|
-
FROM base AS runner
|
|
39
|
-
|
|
40
|
-
WORKDIR /app
|
|
41
|
-
|
|
42
|
-
ENV NODE_ENV=production
|
|
43
|
-
|
|
44
|
-
COPY --from=installer /app .
|
|
45
|
-
|
|
46
|
-
EXPOSE 3000
|
|
47
|
-
|
|
48
|
-
CMD ["pnpm", "start:web"]
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
version: "3.9"
|
|
2
|
-
|
|
3
|
-
services:
|
|
4
|
-
|
|
5
|
-
api:
|
|
6
|
-
build:
|
|
7
|
-
context: ../..
|
|
8
|
-
dockerfile: infrastructure/docker/Dockerfile.api
|
|
9
|
-
container_name: {{projectName}}-api-dev
|
|
10
|
-
env_file:
|
|
11
|
-
- ../../.env
|
|
12
|
-
ports:
|
|
13
|
-
- "4000:4000"
|
|
14
|
-
depends_on:
|
|
15
|
-
- postgres
|
|
16
|
-
- redis
|
|
17
|
-
|
|
18
|
-
web:
|
|
19
|
-
build:
|
|
20
|
-
context: ../..
|
|
21
|
-
dockerfile: infrastructure/docker/Dockerfile.web
|
|
22
|
-
container_name: {{projectName}}-web-dev
|
|
23
|
-
env_file:
|
|
24
|
-
- ../../.env
|
|
25
|
-
ports:
|
|
26
|
-
- "3000:3000"
|
|
27
|
-
|
|
28
|
-
admin:
|
|
29
|
-
build:
|
|
30
|
-
context: ../..
|
|
31
|
-
dockerfile: infrastructure/docker/Dockerfile.admin
|
|
32
|
-
container_name: {{projectName}}-admin-dev
|
|
33
|
-
env_file:
|
|
34
|
-
- ../../.env
|
|
35
|
-
ports:
|
|
36
|
-
- "3001:3001"
|
|
37
|
-
|
|
38
|
-
postgres:
|
|
39
|
-
image: postgres:16
|
|
40
|
-
container_name: {{projectName}}-postgres-dev
|
|
41
|
-
environment:
|
|
42
|
-
POSTGRES_DB: ${POSTGRES_DB}
|
|
43
|
-
POSTGRES_USER: ${POSTGRES_USER}
|
|
44
|
-
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
45
|
-
ports:
|
|
46
|
-
- "5432:5432"
|
|
47
|
-
|
|
48
|
-
redis:
|
|
49
|
-
image: redis:7
|
|
50
|
-
container_name: {{projectName}}-redis-dev
|
|
51
|
-
ports:
|
|
52
|
-
- "6379:6379"
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
version: "3.9"
|
|
2
|
-
|
|
3
|
-
services:
|
|
4
|
-
|
|
5
|
-
traefik:
|
|
6
|
-
image: traefik:v3.0
|
|
7
|
-
ports:
|
|
8
|
-
- "80:80"
|
|
9
|
-
- "443:443"
|
|
10
|
-
volumes:
|
|
11
|
-
- /var/run/docker.sock:/var/run/docker.sock
|
|
12
|
-
- ../traefik/traefik.yml:/etc/traefik/traefik.yml
|
|
13
|
-
- ../traefik/dynamic.yml:/etc/traefik/dynamic.yml
|
|
14
|
-
- ../traefik/acme.json:/etc/traefik/acme.json
|
|
15
|
-
networks:
|
|
16
|
-
- frontend
|
|
17
|
-
restart: always
|
|
18
|
-
|
|
19
|
-
web:
|
|
20
|
-
{{#if isCicd}}
|
|
21
|
-
image: ghcr.io/{{githubUsername}}/{{projectName}}-web:latest
|
|
22
|
-
{{else}}
|
|
23
|
-
build:
|
|
24
|
-
context: ../..
|
|
25
|
-
dockerfile: infrastructure/docker/Dockerfile.web
|
|
26
|
-
{{/if}}
|
|
27
|
-
container_name: {{projectName}}-web
|
|
28
|
-
env_file:
|
|
29
|
-
- ../../.env
|
|
30
|
-
labels:
|
|
31
|
-
- "traefik.enable=true"
|
|
32
|
-
- "traefik.http.routers.web.rule=Host(`app.${DOMAIN}`)"
|
|
33
|
-
- "traefik.http.routers.web.entrypoints=websecure"
|
|
34
|
-
- "traefik.http.routers.web.tls.certresolver=letsencrypt"
|
|
35
|
-
- "traefik.http.services.web.loadbalancer.server.port=3000"
|
|
36
|
-
- "traefik.http.routers.web.middlewares=secureHeaders@file,rateLimit@file"
|
|
37
|
-
healthcheck:
|
|
38
|
-
test: ["CMD", "wget", "-qO-", "http://localhost:3000"]
|
|
39
|
-
interval: 1m30s
|
|
40
|
-
timeout: 30s
|
|
41
|
-
retries: 5
|
|
42
|
-
start_period: 30s
|
|
43
|
-
networks:
|
|
44
|
-
- frontend
|
|
45
|
-
restart: always
|
|
46
|
-
|
|
47
|
-
{{#if includeAdmin}}
|
|
48
|
-
admin:
|
|
49
|
-
{{#if isCicd}}
|
|
50
|
-
image: ghcr.io/{{githubUsername}}/{{projectName}}-admin:latest
|
|
51
|
-
{{else}}
|
|
52
|
-
build:
|
|
53
|
-
context: ../..
|
|
54
|
-
dockerfile: infrastructure/docker/Dockerfile.admin
|
|
55
|
-
{{/if}}
|
|
56
|
-
container_name: {{projectName}}-admin
|
|
57
|
-
env_file:
|
|
58
|
-
- ../../.env
|
|
59
|
-
labels:
|
|
60
|
-
- "traefik.enable=true"
|
|
61
|
-
- "traefik.http.routers.admin.rule=Host(`admin.${DOMAIN}`)"
|
|
62
|
-
- "traefik.http.routers.admin.entrypoints=websecure"
|
|
63
|
-
- "traefik.http.routers.admin.tls.certresolver=letsencrypt"
|
|
64
|
-
- "traefik.http.services.admin.loadbalancer.server.port=3001"
|
|
65
|
-
- "traefik.http.routers.admin.middlewares=secureHeaders@file,rateLimit@file"
|
|
66
|
-
healthcheck:
|
|
67
|
-
test: ["CMD", "wget", "-qO-", "http://localhost:3001"]
|
|
68
|
-
interval: 1m30s
|
|
69
|
-
timeout: 30s
|
|
70
|
-
retries: 5
|
|
71
|
-
start_period: 30s
|
|
72
|
-
networks:
|
|
73
|
-
- frontend
|
|
74
|
-
restart: always
|
|
75
|
-
{{/if}}
|
|
76
|
-
|
|
77
|
-
{{#if includeApi}}
|
|
78
|
-
api:
|
|
79
|
-
{{#if isCicd}}
|
|
80
|
-
image: ghcr.io/{{githubUsername}}/{{projectName}}-api:latest
|
|
81
|
-
{{else}}
|
|
82
|
-
build:
|
|
83
|
-
context: ../..
|
|
84
|
-
dockerfile: infrastructure/docker/Dockerfile.api
|
|
85
|
-
{{/if}}
|
|
86
|
-
container_name: {{projectName}}-api
|
|
87
|
-
env_file:
|
|
88
|
-
- ../../.env
|
|
89
|
-
labels:
|
|
90
|
-
- "traefik.enable=true"
|
|
91
|
-
- "traefik.http.routers.api.rule=Host(`api.${DOMAIN}`)"
|
|
92
|
-
- "traefik.http.routers.api.entrypoints=websecure"
|
|
93
|
-
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
|
|
94
|
-
- "traefik.http.services.api.loadbalancer.server.port=4000"
|
|
95
|
-
- "traefik.http.routers.api.middlewares=secureHeaders@file,rateLimit@file"
|
|
96
|
-
healthcheck:
|
|
97
|
-
test: ["CMD", "wget", "-qO-", "http://localhost:4000/health"]
|
|
98
|
-
interval: 1m30s
|
|
99
|
-
timeout: 30s
|
|
100
|
-
retries: 5
|
|
101
|
-
start_period: 30s
|
|
102
|
-
depends_on:
|
|
103
|
-
postgres:
|
|
104
|
-
condition: service_healthy
|
|
105
|
-
redis:
|
|
106
|
-
condition: service_healthy
|
|
107
|
-
networks:
|
|
108
|
-
- frontend
|
|
109
|
-
- backend
|
|
110
|
-
restart: always
|
|
111
|
-
{{/if}}
|
|
112
|
-
|
|
113
|
-
postgres:
|
|
114
|
-
image: postgres:16
|
|
115
|
-
container_name: {{projectName}}-postgres
|
|
116
|
-
environment:
|
|
117
|
-
POSTGRES_USER: ${POSTGRES_USER}
|
|
118
|
-
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
119
|
-
POSTGRES_DB: ${POSTGRES_DB}
|
|
120
|
-
volumes:
|
|
121
|
-
- postgres_data:/var/lib/postgresql/data
|
|
122
|
-
healthcheck:
|
|
123
|
-
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
|
124
|
-
interval: 10s
|
|
125
|
-
timeout: 5s
|
|
126
|
-
retries: 5
|
|
127
|
-
start_period: 10s
|
|
128
|
-
networks:
|
|
129
|
-
- backend
|
|
130
|
-
restart: always
|
|
131
|
-
|
|
132
|
-
redis:
|
|
133
|
-
image: redis:7
|
|
134
|
-
container_name: {{projectName}}-redis
|
|
135
|
-
healthcheck:
|
|
136
|
-
test: ["CMD", "redis-cli", "ping"]
|
|
137
|
-
interval: 10s
|
|
138
|
-
timeout: 5s
|
|
139
|
-
retries: 5
|
|
140
|
-
start_period: 10s
|
|
141
|
-
networks:
|
|
142
|
-
- backend
|
|
143
|
-
restart: always
|
|
144
|
-
|
|
145
|
-
portainer:
|
|
146
|
-
image: portainer/portainer-ce
|
|
147
|
-
volumes:
|
|
148
|
-
- /var/run/docker.sock:/var/run/docker.sock
|
|
149
|
-
- portainer_data:/data
|
|
150
|
-
labels:
|
|
151
|
-
- "traefik.enable=true"
|
|
152
|
-
- "traefik.http.routers.portainer.rule=Host(`portainer.${DOMAIN}`)"
|
|
153
|
-
- "traefik.http.routers.portainer.entrypoints=websecure"
|
|
154
|
-
- "traefik.http.routers.portainer.tls.certresolver=letsencrypt"
|
|
155
|
-
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
|
|
156
|
-
networks:
|
|
157
|
-
- frontend
|
|
158
|
-
restart: always
|
|
159
|
-
|
|
160
|
-
volumes:
|
|
161
|
-
postgres_data:
|
|
162
|
-
portainer_data:
|
|
163
|
-
|
|
164
|
-
networks:
|
|
165
|
-
frontend:
|
|
166
|
-
backend:
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Deployment Strategy: {{deploymentStrategy}}
|
|
4
|
-
|
|
5
|
-
{{#if isCicd}}
|
|
6
|
-
echo "🚀 Deployment Strategy: Automated CI/CD"
|
|
7
|
-
echo "ℹ️ To deploy, simply commit and push your changes to the 'main' branch."
|
|
8
|
-
echo " git push origin main"
|
|
9
|
-
echo ""
|
|
10
|
-
echo "This will trigger the GitHub Actions workflow defined in .github/workflows/ci-cd.yml"
|
|
11
|
-
{{/if}}
|
|
12
|
-
|
|
13
|
-
{{#if isCoolify}}
|
|
14
|
-
echo "🚀 Deployment Strategy: Coolify"
|
|
15
|
-
echo "ℹ️ To deploy, simply commit and push your changes to the 'main' branch."
|
|
16
|
-
echo " git push origin main"
|
|
17
|
-
echo ""
|
|
18
|
-
echo "Coolify will detect the changes and rebuild your application automatically."
|
|
19
|
-
{{/if}}
|
|
20
|
-
|
|
21
|
-
{{#if isDirect}}
|
|
22
|
-
echo "🚀 Deployment Strategy: Direct Source Build"
|
|
23
|
-
echo "📡 Connecting to server..."
|
|
24
|
-
|
|
25
|
-
# Load environment variables from .env if present (locally) to get DEPLOY_HOST/USER
|
|
26
|
-
if [ -f .env ]; then
|
|
27
|
-
# Export variables from .env
|
|
28
|
-
set -a
|
|
29
|
-
source .env
|
|
30
|
-
set +a
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
# Defaults (replace with your actual server details if not in .env)
|
|
34
|
-
HOST="${DEPLOY_HOST:-your-server-ip}"
|
|
35
|
-
USER="${DEPLOY_USER:-root}"
|
|
36
|
-
DIR="${DEPLOY_PATH:-~/app}"
|
|
37
|
-
|
|
38
|
-
if [ "$HOST" = "your-server-ip" ]; then
|
|
39
|
-
echo "❌ Error: DEPLOY_HOST not set in .env"
|
|
40
|
-
echo "Please add DEPLOY_HOST, DEPLOY_USER, and DEPLOY_PATH to your .env file."
|
|
41
|
-
exit 1
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
echo "Deploying to $USER@$HOST:$DIR..."
|
|
45
|
-
|
|
46
|
-
ssh $USER@$HOST "cd $DIR && git pull && docker compose -f infrastructure/docker/compose.prod.yml up -d --build --remove-orphans"
|
|
47
|
-
|
|
48
|
-
echo "✅ Deployment command sent!"
|
|
49
|
-
{{/if}}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# init-traefik.sh - Initialize Traefik ACME file
|
|
4
|
-
# Usage: ./init-traefik.sh
|
|
5
|
-
|
|
6
|
-
echo "Initializing Traefik ACME file..."
|
|
7
|
-
touch infrastructure/traefik/acme.json
|
|
8
|
-
chmod 600 infrastructure/traefik/acme.json
|
|
9
|
-
|
|
10
|
-
echo "Traefik initialized successfully."
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -e
|
|
3
|
-
|
|
4
|
-
# Setup Server Script
|
|
5
|
-
# Usage: curl -sL https://raw.githubusercontent.com/user/repo/main/infrastructure/scripts/setup-server.sh | bash
|
|
6
|
-
|
|
7
|
-
echo "🚀 Starting Server Setup..."
|
|
8
|
-
|
|
9
|
-
# Update and Install Docker
|
|
10
|
-
echo "📦 Installing Docker..."
|
|
11
|
-
if ! command -v docker &> /dev/null; then
|
|
12
|
-
curl -fsSL https://get.docker.com | sh
|
|
13
|
-
# Add current user to docker group if not root
|
|
14
|
-
if [ "$USER" != "root" ]; then
|
|
15
|
-
sudo usermod -aG docker $USER
|
|
16
|
-
fi
|
|
17
|
-
echo "✅ Docker installed."
|
|
18
|
-
else
|
|
19
|
-
echo "✅ Docker already installed."
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
# Firewall Setup
|
|
23
|
-
echo "🛡️ Configuring Firewall (UFW)..."
|
|
24
|
-
if command -v ufw &> /dev/null; then
|
|
25
|
-
# Check if we have sudo
|
|
26
|
-
if [ "$EUID" -ne 0 ] && command -v sudo &> /dev/null; then
|
|
27
|
-
SUDO="sudo"
|
|
28
|
-
else
|
|
29
|
-
SUDO=""
|
|
30
|
-
fi
|
|
31
|
-
|
|
32
|
-
$SUDO ufw allow 22/tcp
|
|
33
|
-
$SUDO ufw allow 80/tcp
|
|
34
|
-
$SUDO ufw allow 443/tcp
|
|
35
|
-
# ufw enable # Interactive, so we skip enabling automatically
|
|
36
|
-
echo "✅ Firewall rules updated (Ports 22, 80, 443 allowed)."
|
|
37
|
-
else
|
|
38
|
-
echo "⚠️ UFW not found, skipping firewall setup."
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
# Create Networks
|
|
42
|
-
echo "🌐 Creating Docker Networks..."
|
|
43
|
-
if ! docker network inspect traefik-public >/dev/null 2>&1; then
|
|
44
|
-
docker network create traefik-public
|
|
45
|
-
echo "✅ Network 'traefik-public' created."
|
|
46
|
-
else
|
|
47
|
-
echo "✅ Network 'traefik-public' already exists."
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
echo "🎉 Server setup complete! You may need to logout and login for Docker group changes to take effect."
|
|
File without changes
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
http:
|
|
2
|
-
|
|
3
|
-
middlewares:
|
|
4
|
-
|
|
5
|
-
secureHeaders:
|
|
6
|
-
headers:
|
|
7
|
-
|
|
8
|
-
sslRedirect: true
|
|
9
|
-
stsSeconds: 63072000
|
|
10
|
-
stsIncludeSubdomains: true
|
|
11
|
-
stsPreload: true
|
|
12
|
-
|
|
13
|
-
contentTypeNosniff: true
|
|
14
|
-
browserXssFilter: true
|
|
15
|
-
|
|
16
|
-
frameDeny: true
|
|
17
|
-
|
|
18
|
-
rateLimit:
|
|
19
|
-
rateLimit:
|
|
20
|
-
average: 100
|
|
21
|
-
burst: 50
|
|
22
|
-
|
|
23
|
-
routers: {}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
api:
|
|
2
|
-
dashboard: true
|
|
3
|
-
|
|
4
|
-
entryPoints:
|
|
5
|
-
|
|
6
|
-
web:
|
|
7
|
-
address: ":80"
|
|
8
|
-
http:
|
|
9
|
-
redirections:
|
|
10
|
-
entryPoint:
|
|
11
|
-
to: websecure
|
|
12
|
-
scheme: https
|
|
13
|
-
|
|
14
|
-
websecure:
|
|
15
|
-
address: ":443"
|
|
16
|
-
|
|
17
|
-
providers:
|
|
18
|
-
|
|
19
|
-
docker:
|
|
20
|
-
exposedByDefault: false
|
|
21
|
-
|
|
22
|
-
file:
|
|
23
|
-
filename: /etc/traefik/dynamic.yml
|
|
24
|
-
|
|
25
|
-
certificatesResolvers:
|
|
26
|
-
|
|
27
|
-
letsencrypt:
|
|
28
|
-
acme:
|
|
29
|
-
storage: /etc/traefik/acme.json
|
|
30
|
-
httpChallenge:
|
|
31
|
-
entryPoint: web
|