nvoi 0.1.5

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.
Files changed (178) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +19 -0
  3. data/Gemfile +9 -0
  4. data/Gemfile.lock +151 -0
  5. data/Makefile +26 -0
  6. data/Rakefile +16 -0
  7. data/doc/config-schema.yaml +357 -0
  8. data/examples/apex-wildcard/deploy.yml +68 -0
  9. data/examples/golang/.gitignore +19 -0
  10. data/examples/golang/Dockerfile +43 -0
  11. data/examples/golang/README.md +59 -0
  12. data/examples/golang/deploy.enc +0 -0
  13. data/examples/golang/deploy.yml +54 -0
  14. data/examples/golang/go.mod +39 -0
  15. data/examples/golang/go.sum +96 -0
  16. data/examples/golang/main.go +177 -0
  17. data/examples/golang/models/user.go +17 -0
  18. data/examples/golang-postgres-multi/.gitignore +18 -0
  19. data/examples/golang-postgres-multi/Dockerfile +39 -0
  20. data/examples/golang-postgres-multi/README.md +211 -0
  21. data/examples/golang-postgres-multi/deploy.yml +67 -0
  22. data/examples/golang-postgres-multi/go.mod +45 -0
  23. data/examples/golang-postgres-multi/go.sum +108 -0
  24. data/examples/golang-postgres-multi/main.go +197 -0
  25. data/examples/golang-postgres-multi/models/user.go +17 -0
  26. data/examples/postgres-multi/.env.production.example +11 -0
  27. data/examples/postgres-multi/README.md +112 -0
  28. data/examples/postgres-multi/deploy.yml +74 -0
  29. data/examples/postgres-single/.env.production.example +11 -0
  30. data/examples/postgres-single/.gitignore +15 -0
  31. data/examples/postgres-single/Dockerfile +35 -0
  32. data/examples/postgres-single/README.md +76 -0
  33. data/examples/postgres-single/deploy.yml +56 -0
  34. data/examples/postgres-single/go.mod +45 -0
  35. data/examples/postgres-single/go.sum +108 -0
  36. data/examples/postgres-single/main.go +184 -0
  37. data/examples/rails-single/.dockerignore +51 -0
  38. data/examples/rails-single/.env.production.example +11 -0
  39. data/examples/rails-single/.github/dependabot.yml +12 -0
  40. data/examples/rails-single/.github/workflows/ci.yml +39 -0
  41. data/examples/rails-single/.gitignore +20 -0
  42. data/examples/rails-single/.node-version +1 -0
  43. data/examples/rails-single/.rubocop.yml +8 -0
  44. data/examples/rails-single/.ruby-version +1 -0
  45. data/examples/rails-single/Dockerfile +86 -0
  46. data/examples/rails-single/Gemfile +56 -0
  47. data/examples/rails-single/Gemfile.lock +350 -0
  48. data/examples/rails-single/Procfile.dev +3 -0
  49. data/examples/rails-single/README.md +17 -0
  50. data/examples/rails-single/Rakefile +6 -0
  51. data/examples/rails-single/app/assets/builds/.keep +0 -0
  52. data/examples/rails-single/app/assets/images/.keep +0 -0
  53. data/examples/rails-single/app/assets/stylesheets/application.tailwind.css +1 -0
  54. data/examples/rails-single/app/controllers/application_controller.rb +4 -0
  55. data/examples/rails-single/app/controllers/concerns/.keep +0 -0
  56. data/examples/rails-single/app/controllers/users_controller.rb +19 -0
  57. data/examples/rails-single/app/helpers/application_helper.rb +2 -0
  58. data/examples/rails-single/app/javascript/application.js +3 -0
  59. data/examples/rails-single/app/javascript/controllers/application.js +9 -0
  60. data/examples/rails-single/app/javascript/controllers/hello_controller.js +7 -0
  61. data/examples/rails-single/app/javascript/controllers/index.js +8 -0
  62. data/examples/rails-single/app/jobs/application_job.rb +7 -0
  63. data/examples/rails-single/app/mailers/application_mailer.rb +4 -0
  64. data/examples/rails-single/app/models/application_record.rb +3 -0
  65. data/examples/rails-single/app/models/concerns/.keep +0 -0
  66. data/examples/rails-single/app/models/user.rb +2 -0
  67. data/examples/rails-single/app/views/layouts/application.html.erb +28 -0
  68. data/examples/rails-single/app/views/layouts/mailer.html.erb +13 -0
  69. data/examples/rails-single/app/views/layouts/mailer.text.erb +1 -0
  70. data/examples/rails-single/app/views/pwa/manifest.json.erb +22 -0
  71. data/examples/rails-single/app/views/pwa/service-worker.js +26 -0
  72. data/examples/rails-single/app/views/users/index.html.erb +38 -0
  73. data/examples/rails-single/bin/brakeman +7 -0
  74. data/examples/rails-single/bin/bundle +109 -0
  75. data/examples/rails-single/bin/dev +11 -0
  76. data/examples/rails-single/bin/docker-entrypoint +14 -0
  77. data/examples/rails-single/bin/jobs +6 -0
  78. data/examples/rails-single/bin/kamal +27 -0
  79. data/examples/rails-single/bin/rails +4 -0
  80. data/examples/rails-single/bin/rake +4 -0
  81. data/examples/rails-single/bin/rubocop +8 -0
  82. data/examples/rails-single/bin/setup +37 -0
  83. data/examples/rails-single/bin/thrust +5 -0
  84. data/examples/rails-single/bun.lock +224 -0
  85. data/examples/rails-single/config/application.rb +42 -0
  86. data/examples/rails-single/config/boot.rb +4 -0
  87. data/examples/rails-single/config/cable.yml +17 -0
  88. data/examples/rails-single/config/cache.yml +16 -0
  89. data/examples/rails-single/config/credentials.yml.enc +1 -0
  90. data/examples/rails-single/config/database.yml +100 -0
  91. data/examples/rails-single/config/environment.rb +5 -0
  92. data/examples/rails-single/config/environments/development.rb +69 -0
  93. data/examples/rails-single/config/environments/production.rb +87 -0
  94. data/examples/rails-single/config/environments/test.rb +50 -0
  95. data/examples/rails-single/config/initializers/assets.rb +7 -0
  96. data/examples/rails-single/config/initializers/content_security_policy.rb +25 -0
  97. data/examples/rails-single/config/initializers/filter_parameter_logging.rb +8 -0
  98. data/examples/rails-single/config/initializers/inflections.rb +16 -0
  99. data/examples/rails-single/config/locales/en.yml +31 -0
  100. data/examples/rails-single/config/puma.rb +41 -0
  101. data/examples/rails-single/config/queue.yml +18 -0
  102. data/examples/rails-single/config/recurring.yml +15 -0
  103. data/examples/rails-single/config/routes.rb +4 -0
  104. data/examples/rails-single/config.ru +6 -0
  105. data/examples/rails-single/db/cable_schema.rb +11 -0
  106. data/examples/rails-single/db/cache_schema.rb +12 -0
  107. data/examples/rails-single/db/migrate/20251123095526_create_users.rb +10 -0
  108. data/examples/rails-single/db/queue_schema.rb +129 -0
  109. data/examples/rails-single/db/seeds.rb +9 -0
  110. data/examples/rails-single/deploy.yml +57 -0
  111. data/examples/rails-single/lib/tasks/.keep +0 -0
  112. data/examples/rails-single/log/.keep +0 -0
  113. data/examples/rails-single/package.json +17 -0
  114. data/examples/rails-single/public/400.html +114 -0
  115. data/examples/rails-single/public/404.html +114 -0
  116. data/examples/rails-single/public/406-unsupported-browser.html +114 -0
  117. data/examples/rails-single/public/422.html +114 -0
  118. data/examples/rails-single/public/500.html +114 -0
  119. data/examples/rails-single/public/icon.png +0 -0
  120. data/examples/rails-single/public/icon.svg +3 -0
  121. data/examples/rails-single/public/robots.txt +1 -0
  122. data/examples/rails-single/script/.keep +0 -0
  123. data/examples/rails-single/vendor/.keep +0 -0
  124. data/examples/rails-single/yarn.lock +188 -0
  125. data/exe/nvoi +6 -0
  126. data/lib/nvoi/cli.rb +190 -0
  127. data/lib/nvoi/cloudflare/client.rb +287 -0
  128. data/lib/nvoi/config/config.rb +248 -0
  129. data/lib/nvoi/config/env_resolver.rb +63 -0
  130. data/lib/nvoi/config/loader.rb +102 -0
  131. data/lib/nvoi/config/naming.rb +196 -0
  132. data/lib/nvoi/config/ssh_keys.rb +82 -0
  133. data/lib/nvoi/config/types.rb +274 -0
  134. data/lib/nvoi/constants.rb +59 -0
  135. data/lib/nvoi/credentials/crypto.rb +88 -0
  136. data/lib/nvoi/credentials/editor.rb +272 -0
  137. data/lib/nvoi/credentials/manager.rb +173 -0
  138. data/lib/nvoi/deployer/cleaner.rb +36 -0
  139. data/lib/nvoi/deployer/image_builder.rb +23 -0
  140. data/lib/nvoi/deployer/infrastructure.rb +126 -0
  141. data/lib/nvoi/deployer/orchestrator.rb +146 -0
  142. data/lib/nvoi/deployer/retry.rb +67 -0
  143. data/lib/nvoi/deployer/service_deployer.rb +311 -0
  144. data/lib/nvoi/deployer/tunnel_manager.rb +57 -0
  145. data/lib/nvoi/deployer/types.rb +8 -0
  146. data/lib/nvoi/errors.rb +67 -0
  147. data/lib/nvoi/k8s/renderer.rb +44 -0
  148. data/lib/nvoi/k8s/templates.rb +29 -0
  149. data/lib/nvoi/logger.rb +72 -0
  150. data/lib/nvoi/providers/aws.rb +403 -0
  151. data/lib/nvoi/providers/base.rb +111 -0
  152. data/lib/nvoi/providers/hetzner.rb +288 -0
  153. data/lib/nvoi/providers/hetzner_client.rb +170 -0
  154. data/lib/nvoi/remote/docker_manager.rb +203 -0
  155. data/lib/nvoi/remote/ssh_executor.rb +72 -0
  156. data/lib/nvoi/remote/volume_manager.rb +103 -0
  157. data/lib/nvoi/service/delete.rb +234 -0
  158. data/lib/nvoi/service/deploy.rb +80 -0
  159. data/lib/nvoi/service/exec.rb +144 -0
  160. data/lib/nvoi/service/provider.rb +36 -0
  161. data/lib/nvoi/steps/application_deployer.rb +26 -0
  162. data/lib/nvoi/steps/database_provisioner.rb +60 -0
  163. data/lib/nvoi/steps/k3s_cluster_setup.rb +105 -0
  164. data/lib/nvoi/steps/k3s_provisioner.rb +351 -0
  165. data/lib/nvoi/steps/server_provisioner.rb +43 -0
  166. data/lib/nvoi/steps/services_provisioner.rb +29 -0
  167. data/lib/nvoi/steps/tunnel_configurator.rb +66 -0
  168. data/lib/nvoi/steps/volume_provisioner.rb +154 -0
  169. data/lib/nvoi/version.rb +5 -0
  170. data/lib/nvoi.rb +79 -0
  171. data/templates/app-deployment.yaml.erb +102 -0
  172. data/templates/app-ingress.yaml.erb +20 -0
  173. data/templates/app-secret.yaml.erb +10 -0
  174. data/templates/app-service.yaml.erb +12 -0
  175. data/templates/db-statefulset.yaml.erb +76 -0
  176. data/templates/service-deployment.yaml.erb +91 -0
  177. data/templates/worker-deployment.yaml.erb +50 -0
  178. metadata +361 -0
@@ -0,0 +1,112 @@
1
+ # PostgreSQL Multi-Instance Example
2
+
3
+ Production setup with app on master server and PostgreSQL on dedicated worker server.
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ ┌─────────────────────────────────────┐
9
+ │ Master Server (cx32) │
10
+ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
11
+ │ K3s Server Mode │
12
+ │ │
13
+ │ ┌──────────────────────────────┐ │
14
+ │ │ App Pod │ │
15
+ │ │ - Port 3000 │ │
16
+ │ │ - Connects to: │ │
17
+ │ │ postgres-service:5432 │ │
18
+ │ └──────────────────────────────┘ │
19
+ │ │
20
+ │ Private IP: 10.0.0.1 │
21
+ └─────────────────────────────────────┘
22
+
23
+ │ K3s Cluster Network (WireGuard)
24
+
25
+ ┌─────────────────────────────────────┐
26
+ │ Worker Server (cx42) │
27
+ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
28
+ │ K3s Agent Mode │
29
+ │ │
30
+ │ ┌──────────────────────────────┐ │
31
+ │ │ PostgreSQL StatefulSet │ │
32
+ │ │ - Service: postgres-service │ │
33
+ │ │ - Port: 5432 │ │
34
+ │ │ - Volume: /var/lib/postgres │ │
35
+ │ └──────────────────────────────┘ │
36
+ │ │
37
+ │ Private IP: 10.0.0.2 │
38
+ │ Volume: /opt/postgres_data │
39
+ └─────────────────────────────────────┘
40
+ ```
41
+
42
+ ## Cost
43
+
44
+ - **Master**: 1x cx32 (~€10/month)
45
+ - **Worker**: 1x cx42 (~€15/month)
46
+ - **Total**: ~€25/month
47
+
48
+ ## Benefits
49
+
50
+ 1. **Resource Isolation**: Database gets dedicated server resources
51
+ 2. **Better Performance**: App and DB don't compete for CPU/memory
52
+ 3. **Scalability**: Can add more workers for distributed workloads
53
+ 4. **High Availability**: Foundation for future HA setups
54
+
55
+ ## Setup
56
+
57
+ 1. **Copy environment file**:
58
+ ```bash
59
+ cp .env.production.example .env.production
60
+ ```
61
+
62
+ 2. **Edit `.env.production`** with your credentials:
63
+ ```bash
64
+ CLOUDFLARE_API_TOKEN=your_token
65
+ CLOUDFLARE_ACCOUNT_ID=your_account_id
66
+ HETZNER_API_TOKEN=your_token
67
+ DB_PASSWORD=your_secure_password
68
+ SECRET_KEY_BASE=$(openssl rand -hex 64)
69
+ JWT_SECRET=$(openssl rand -hex 32)
70
+ ```
71
+
72
+ 3. **Deploy**:
73
+ ```bash
74
+ nvoi-cli deploy --config examples/postgres-multi/deploy.yml
75
+ ```
76
+
77
+ ## Verification
78
+
79
+ ```bash
80
+ # SSH to master
81
+ ssh root@<master-ip>
82
+
83
+ # Check PostgreSQL pod (should be on worker node)
84
+ kubectl get pods -o wide | grep postgres
85
+
86
+ # SSH to worker node
87
+ ssh root@<worker-ip>
88
+
89
+ # Check volume on worker
90
+ ls -la /opt/postgres_data/
91
+
92
+ # From master: Test service DNS
93
+ kubectl run -it --rm debug --image=postgres:16-alpine --restart=Never -- \
94
+ psql postgresql://appuser:$DB_PASSWORD@postgres-service:5432/app_production -c '\dt'
95
+ ```
96
+
97
+ ## How It Works
98
+
99
+ 1. **Master Server**: Runs K3s in server mode, hosts the app
100
+ 2. **Worker Server**: Joins K3s cluster as agent, runs PostgreSQL
101
+ 3. **K3s Networking**: Private network (10.0.0.0/16) between nodes
102
+ 4. **Service DNS**: App connects via `postgres-service:5432`
103
+ 5. **Volume**: PostgreSQL data persists on worker node filesystem
104
+
105
+ ## Features
106
+
107
+ - ✅ PostgreSQL 16 Alpine on dedicated server
108
+ - ✅ Persistent data storage on worker
109
+ - ✅ K3s service discovery
110
+ - ✅ Private cluster networking
111
+ - ✅ Resource isolation
112
+ - ✅ Production-ready setup
@@ -0,0 +1,74 @@
1
+ application:
2
+ name: example-postgres-multinode
3
+ environment: production
4
+
5
+ # Provider configuration
6
+ domain_provider:
7
+ cloudflare:
8
+ api_token: $CLOUDFLARE_API_TOKEN
9
+ account_id: $CLOUDFLARE_ACCOUNT_ID
10
+
11
+ compute_provider:
12
+ hetzner:
13
+ api_token: $HETZNER_API_TOKEN
14
+ server_type: cx22 # Default for all servers
15
+ server_location: nbg1
16
+
17
+ # Multi-instance server configuration: 4 servers total
18
+ servers:
19
+ master:
20
+ master: true
21
+ type: cx22 # Control plane only, no workloads
22
+ location: nbg1
23
+
24
+ workers:
25
+ type: cx32 # App servers
26
+ count: 2
27
+ location: nbg1
28
+
29
+ database:
30
+ type: cx42 # Dedicated database server
31
+ location: nbg1
32
+
33
+ # Container retention
34
+ keep_count: 2
35
+
36
+ # Application secrets
37
+ secrets:
38
+ SECRET_KEY_BASE: $SECRET_KEY_BASE
39
+ JWT_SECRET: $JWT_SECRET
40
+
41
+ # Application service (runs on workers with 2 replicas)
42
+ app:
43
+ web:
44
+ servers: [workers]
45
+ domain: rb.run
46
+ subdomain: postgres-multi
47
+ port: 3000
48
+ healthcheck:
49
+ type: http
50
+ path: /health
51
+ port: 3000
52
+ interval: 10s
53
+ timeout: 5s
54
+ retries: 3
55
+ env:
56
+ # PostgreSQL connection via K3s service DNS
57
+ DATABASE_URL: postgresql://appuser:$DB_PASSWORD@db-example-postgres-multinode:5432/app_production
58
+ RAILS_ENV: production
59
+
60
+ # PostgreSQL database (runs on dedicated database server)
61
+ database:
62
+ servers: [database]
63
+ adapter: postgres
64
+ image: postgres:16-alpine
65
+ volume: postgres_data
66
+ secrets:
67
+ POSTGRES_DB: app_production
68
+ POSTGRES_USER: appuser
69
+ POSTGRES_PASSWORD: $DB_PASSWORD
70
+
71
+ # Environment variables
72
+ env:
73
+ APP_NAME: postgres-multi-demo
74
+ LOG_LEVEL: info
@@ -0,0 +1,11 @@
1
+ # Provider credentials (required)
2
+ CLOUDFLARE_API_TOKEN=your_cloudflare_token_here
3
+ CLOUDFLARE_ACCOUNT_ID=your_cloudflare_account_id_here
4
+ HETZNER_API_TOKEN=your_hetzner_token_here
5
+
6
+ # Database password
7
+ DB_PASSWORD=your_secure_db_password_here
8
+
9
+ # Application secrets
10
+ SECRET_KEY_BASE=generate_with_openssl_rand_hex_64
11
+ JWT_SECRET=generate_with_openssl_rand_hex_32
@@ -0,0 +1,15 @@
1
+ # Binaries
2
+ app
3
+ *.exe
4
+
5
+ # Environment files (except examples)
6
+ .env
7
+ !.env.production.example
8
+
9
+ # IDE
10
+ .idea/
11
+ .vscode/
12
+ *.swp
13
+
14
+ # OS
15
+ .DS_Store
@@ -0,0 +1,35 @@
1
+ # Multi-stage build for optimized image size
2
+
3
+ # Stage 1: Build
4
+ FROM golang:1.23-alpine AS builder
5
+
6
+ WORKDIR /app
7
+
8
+ # Copy dependency files
9
+ COPY go.mod go.sum ./
10
+
11
+ # Download dependencies
12
+ RUN go mod download
13
+
14
+ # Copy source code
15
+ COPY . .
16
+
17
+ # Build the application
18
+ RUN CGO_ENABLED=0 GOOS=linux go build -o app .
19
+
20
+ # Stage 2: Runtime
21
+ FROM alpine:latest
22
+
23
+ # Install runtime dependencies
24
+ RUN apk --no-cache add ca-certificates
25
+
26
+ WORKDIR /app
27
+
28
+ # Copy binary from builder
29
+ COPY --from=builder /app/app .
30
+
31
+ # Expose port
32
+ EXPOSE 3000
33
+
34
+ # Run the application
35
+ CMD ["./app"]
@@ -0,0 +1,76 @@
1
+ # PostgreSQL Single Instance Example
2
+
3
+ Simple deployment with app and PostgreSQL database on one server.
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ ┌─────────────────────────────────────┐
9
+ │ Server (cx32) │
10
+ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
11
+ │ │
12
+ │ ┌──────────────────────────────┐ │
13
+ │ │ App Container │ │
14
+ │ │ - Port 3000 │ │
15
+ │ │ - Connects to localhost:5432 │ │
16
+ │ └──────────────────────────────┘ │
17
+ │ │
18
+ │ ┌──────────────────────────────┐ │
19
+ │ │ PostgreSQL Container │ │
20
+ │ │ - Port 5432 │ │
21
+ │ │ - Volume: postgres_data │ │
22
+ │ └──────────────────────────────┘ │
23
+ │ │
24
+ └─────────────────────────────────────┘
25
+ ```
26
+
27
+ ## Cost
28
+
29
+ - **Server**: 1x cx32 (~€10/month)
30
+ - **Total**: ~€10/month
31
+
32
+ ## Setup
33
+
34
+ 1. **Copy environment file**:
35
+ ```bash
36
+ cp .env.production.example .env.production
37
+ ```
38
+
39
+ 2. **Edit `.env.production`** with your credentials:
40
+ ```bash
41
+ CLOUDFLARE_API_TOKEN=your_token
42
+ CLOUDFLARE_ACCOUNT_ID=your_account_id
43
+ HETZNER_API_TOKEN=your_token
44
+ DB_PASSWORD=your_secure_password
45
+ SECRET_KEY_BASE=$(openssl rand -hex 64)
46
+ JWT_SECRET=$(openssl rand -hex 32)
47
+ ```
48
+
49
+ 3. **Deploy**:
50
+ ```bash
51
+ nvoi-cli deploy --config examples/postgres-single/deploy.yml
52
+ ```
53
+
54
+ ## Verification
55
+
56
+ ```bash
57
+ # SSH to server
58
+ ssh root@<server-ip>
59
+
60
+ # Check PostgreSQL pod
61
+ kubectl get pods | grep postgres
62
+
63
+ # Check volume
64
+ ls -la /opt/postgres_data/
65
+
66
+ # Test connection
67
+ kubectl exec -it postgres-0 -- psql -U appuser -d app_production -c '\dt'
68
+ ```
69
+
70
+ ## Features
71
+
72
+ - ✅ PostgreSQL 16 Alpine
73
+ - ✅ Persistent data storage
74
+ - ✅ Health checks
75
+ - ✅ Automatic backups (via volume)
76
+ - ✅ Simple single-server setup
@@ -0,0 +1,56 @@
1
+ application:
2
+ name: example-postgres
3
+ environment: production
4
+
5
+ # Provider configuration
6
+ domain_provider:
7
+ cloudflare:
8
+ api_token: $CLOUDFLARE_API_TOKEN
9
+ account_id: $CLOUDFLARE_ACCOUNT_ID
10
+
11
+ compute_provider:
12
+ hetzner:
13
+ api_token: $HETZNER_API_TOKEN
14
+ server_type: cx22
15
+ server_location: fsn1
16
+
17
+ # Server configuration (single server, master: true is implicit)
18
+ servers:
19
+ master:
20
+ type: cx22
21
+ location: fsn1
22
+
23
+ # Container retention
24
+ keep_count: 2
25
+
26
+ # Application service
27
+ app:
28
+ web:
29
+ servers: [master]
30
+ domain: rb.run
31
+ subdomain: go-pg
32
+ port: 3000
33
+ healthcheck:
34
+ type: http
35
+ path: /health
36
+ port: 3000
37
+ interval: 10s
38
+ timeout: 5s
39
+ retries: 3
40
+
41
+ # PostgreSQL database (runs on same server)
42
+ database:
43
+ servers: [master]
44
+ adapter: postgres
45
+ image: postgres:16-alpine
46
+ volume: postgres_data
47
+ secrets:
48
+ POSTGRES_DB: app_production
49
+ POSTGRES_USER: appuser
50
+ POSTGRES_PASSWORD: $DB_PASSWORD
51
+
52
+ # Environment variables (DATABASE_URL auto-injected from database config)
53
+ env:
54
+ APP_NAME: go-postgres-demo
55
+ LOG_LEVEL: info
56
+ GIN_MODE: release
@@ -0,0 +1,45 @@
1
+ module github.com/nvoi/example-postgres
2
+
3
+ go 1.23
4
+
5
+ toolchain go1.24.4
6
+
7
+ require (
8
+ github.com/gin-gonic/gin v1.9.1
9
+ gorm.io/driver/postgres v1.5.4
10
+ gorm.io/gorm v1.25.5
11
+ )
12
+
13
+ require (
14
+ github.com/bytedance/sonic v1.9.1 // indirect
15
+ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
16
+ github.com/gabriel-vasile/mimetype v1.4.2 // indirect
17
+ github.com/gin-contrib/sse v0.1.0 // indirect
18
+ github.com/go-playground/locales v0.14.1 // indirect
19
+ github.com/go-playground/universal-translator v0.18.1 // indirect
20
+ github.com/go-playground/validator/v10 v10.14.0 // indirect
21
+ github.com/goccy/go-json v0.10.2 // indirect
22
+ github.com/jackc/pgpassfile v1.0.0 // indirect
23
+ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
24
+ github.com/jackc/pgx/v5 v5.4.3 // indirect
25
+ github.com/jinzhu/inflection v1.0.0 // indirect
26
+ github.com/jinzhu/now v1.1.5 // indirect
27
+ github.com/json-iterator/go v1.1.12 // indirect
28
+ github.com/klauspost/cpuid/v2 v2.2.4 // indirect
29
+ github.com/kr/text v0.2.0 // indirect
30
+ github.com/leodido/go-urn v1.2.4 // indirect
31
+ github.com/mattn/go-isatty v0.0.19 // indirect
32
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
33
+ github.com/modern-go/reflect2 v1.0.2 // indirect
34
+ github.com/pelletier/go-toml/v2 v2.0.8 // indirect
35
+ github.com/rogpeppe/go-internal v1.14.1 // indirect
36
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
37
+ github.com/ugorji/go/codec v1.2.11 // indirect
38
+ golang.org/x/arch v0.3.0 // indirect
39
+ golang.org/x/crypto v0.14.0 // indirect
40
+ golang.org/x/net v0.10.0 // indirect
41
+ golang.org/x/sys v0.26.0 // indirect
42
+ golang.org/x/text v0.13.0 // indirect
43
+ google.golang.org/protobuf v1.30.0 // indirect
44
+ gopkg.in/yaml.v3 v3.0.1 // indirect
45
+ )
@@ -0,0 +1,108 @@
1
+ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
2
+ github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
3
+ github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
4
+ github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
5
+ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
6
+ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
7
+ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
8
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
10
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
11
+ github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
12
+ github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
13
+ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
14
+ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
15
+ github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
16
+ github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
17
+ github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
18
+ github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
19
+ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
20
+ github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
21
+ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
22
+ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
23
+ github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
24
+ github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
25
+ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
26
+ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
27
+ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
28
+ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
29
+ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
30
+ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
31
+ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
32
+ github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
33
+ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
34
+ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
35
+ github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
36
+ github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
37
+ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
38
+ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
39
+ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
40
+ github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
41
+ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
42
+ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
43
+ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
44
+ github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
45
+ github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
46
+ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
47
+ github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
48
+ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
49
+ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
50
+ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
51
+ github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
52
+ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
53
+ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
54
+ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
55
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
56
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
57
+ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
58
+ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
59
+ github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
60
+ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
61
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
62
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
63
+ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
64
+ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
65
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
66
+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
67
+ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
68
+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
69
+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
70
+ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
71
+ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
72
+ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
73
+ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
74
+ github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
75
+ github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
76
+ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
77
+ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
78
+ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
79
+ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
80
+ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
81
+ golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
82
+ golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
83
+ golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
84
+ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
85
+ golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
86
+ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
87
+ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
88
+ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
89
+ golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
90
+ golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
91
+ golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
92
+ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
93
+ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
94
+ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
95
+ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
96
+ google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
97
+ google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
98
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
99
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
100
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
101
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
102
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
103
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
104
+ gorm.io/driver/postgres v1.5.4 h1:Iyrp9Meh3GmbSuyIAGyjkN+n9K+GHX9b9MqsTL4EJCo=
105
+ gorm.io/driver/postgres v1.5.4/go.mod h1:Bgo89+h0CRcdA33Y6frlaHHVuTdOf87pmyzwW9C/BH0=
106
+ gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
107
+ gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
108
+ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=