-
Notifications
You must be signed in to change notification settings - Fork 8
feat(deploy): one-click deploy buttons and README screenshots #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| { | ||
| "name": "Louez", | ||
| "description": "Open-source equipment rental platform: a branded booking storefront with live availability, plus a back office for reservations, customers, PDF contracts and revenue statistics.", | ||
| "repository": "https://github.com/Synapsr/Louez", | ||
| "website": "https://louez.io", | ||
| "logo": "https://raw.githubusercontent.com/Synapsr/Louez/main/apps/web/public/icons/icon-512.png", | ||
| "keywords": [ | ||
| "rental", | ||
| "booking", | ||
| "reservations", | ||
| "inventory-management", | ||
| "storefront", | ||
| "nextjs", | ||
| "self-hosted" | ||
| ], | ||
| "stack": "container", | ||
| "formation": { | ||
| "web": { | ||
| "quantity": 1, | ||
| "size": "basic" | ||
| } | ||
| }, | ||
| "addons": [ | ||
| { | ||
| "plan": "jawsdb", | ||
| "as": "DATABASE" | ||
| } | ||
| ], | ||
| "env": { | ||
| "LOUEZ_MODE": { | ||
| "description": "standalone hosts a single store at the root of the site, with the dashboard under /dashboard.", | ||
| "value": "standalone" | ||
| }, | ||
| "AUTH_URL": { | ||
| "description": "Public URL of this app — https://<the app name you chose above>.herokuapp.com, or your own domain. Sign-in is bound to it.", | ||
| "required": true | ||
| }, | ||
| "AUTH_SECRET": { | ||
| "description": "Signs sessions. Generated for you.", | ||
| "generator": "secret" | ||
| }, | ||
| "AUTH_TRUST_HOST": { | ||
| "description": "Required behind the Heroku router.", | ||
| "value": "true" | ||
| }, | ||
| "S3_ENDPOINT": { | ||
| "description": "S3-compatible endpoint for product images (AWS S3, Cloudflare R2, Scaleway, Backblaze B2...). Image uploads stay disabled until the five S3 values are set. Everything else works without them.", | ||
| "required": false | ||
| }, | ||
| "S3_REGION": { | ||
| "description": "Region of your bucket, e.g. eu-west-3.", | ||
| "required": false | ||
| }, | ||
| "S3_BUCKET": { | ||
| "description": "Name of your bucket.", | ||
| "required": false | ||
| }, | ||
| "S3_ACCESS_KEY_ID": { | ||
| "description": "Access key with read/write access to the bucket.", | ||
| "required": false | ||
| }, | ||
| "S3_SECRET_ACCESS_KEY": { | ||
| "description": "Secret key paired with the access key.", | ||
| "required": false | ||
| }, | ||
| "S3_PUBLIC_URL": { | ||
| "description": "Public base URL of the bucket, or /files to serve images through the app when the bucket is private.", | ||
| "value": "/files", | ||
| "required": false | ||
| }, | ||
| "SMTP_HOST": { | ||
| "description": "Optional. Without SMTP credentials you sign in with a password and Louez skips sending mail.", | ||
| "required": false | ||
| }, | ||
| "SMTP_PORT": { | ||
| "description": "Optional. 587 for STARTTLS, 465 for TLS on connect.", | ||
| "value": "587", | ||
| "required": false | ||
| }, | ||
| "SMTP_USER": { | ||
| "description": "Optional. SMTP username.", | ||
| "required": false | ||
| }, | ||
| "SMTP_PASSWORD": { | ||
| "description": "Optional. SMTP password.", | ||
| "required": false | ||
| }, | ||
| "SMTP_FROM": { | ||
| "description": "Optional. Sender address, e.g. Louez <noreply@example.com>.", | ||
| "required": false | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # syntax=docker/dockerfile:1 | ||
|
|
||
| # ============================================================================= | ||
| # Louez image store — MinIO with the product bucket pre-created | ||
| # ============================================================================= | ||
| # A bucket is a top-level directory of MinIO's data drive, so creating it at | ||
| # startup replaces the one-shot `mc` job the Compose stack uses. This exists | ||
| # for platforms that run long-lived services only and cannot override a | ||
| # container's entrypoint (Render), where the upstream image would otherwise | ||
| # prepend `minio` to the shell command and refuse to start. | ||
| # | ||
| # Build: docker build -f docker/Dockerfile.minio -t louez-minio docker | ||
| # ============================================================================= | ||
|
|
||
| FROM minio/minio:RELEASE.2025-09-07T16-13-09Z | ||
|
|
||
| EXPOSE 9000 | ||
|
|
||
| ENTRYPOINT ["/bin/sh", "-c"] | ||
| CMD ["mkdir -p /data/${S3_BUCKET:-louez} && exec minio server /data"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Heroku container build — https://devcenter.heroku.com/articles/build-docker-images-heroku-yml | ||
| # | ||
| # Builds the production image from the repository (final stage of | ||
| # docker/Dockerfile.web) and starts it through the same entrypoint the | ||
| # published image uses, so the JawsDB connection string provisioned by app.json | ||
| # is picked up as DATABASE_URL. | ||
| build: | ||
| docker: | ||
| web: docker/Dockerfile.web | ||
| run: | ||
| web: ./docker/entrypoint.sh node apps/web/server.js |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| # Render Blueprint — https://render.com/docs/infrastructure-as-code | ||
| # | ||
| # Deploys Louez in single-store mode with its own MySQL database and a private | ||
| # MinIO store for product images. Louez installs its schema on first boot and | ||
| # derives its public URL from RENDER_EXTERNAL_URL, so the only prompt is the | ||
| # database password. | ||
| # | ||
| # All three services are paid instance types: private services and persistent | ||
| # disks are not available on Render's free tier. | ||
|
|
||
| services: | ||
| - type: web | ||
| name: louez | ||
| runtime: image | ||
| plan: starter | ||
| region: frankfurt | ||
| image: | ||
| url: docker.io/synapsr/louez:2 | ||
| autoDeployTrigger: "off" | ||
| healthCheckPath: /api/health | ||
| envVars: | ||
| - key: LOUEZ_MODE | ||
| value: standalone | ||
| - key: AUTH_TRUST_HOST | ||
| value: "true" | ||
| # Kept out of the container's /app/data so the service needs no disk: | ||
| # Render stores the generated value with the service. | ||
| - key: AUTH_SECRET | ||
| generateValue: true | ||
| # DATABASE_URL is composed in dockerCommand below from this password — | ||
| # a Blueprint cannot concatenate values itself. | ||
| - key: MYSQL_PASSWORD | ||
| fromService: | ||
| type: pserv | ||
| name: louez-mysql | ||
| envVarKey: MYSQL_ROOT_PASSWORD | ||
| # The bucket stays private: Louez streams images same-origin under /files | ||
| # with its own credentials, so the store needs no public URL. | ||
| - key: S3_ENDPOINT | ||
| value: http://louez-minio:9000 | ||
| - key: S3_REGION | ||
| value: us-east-1 | ||
| - key: S3_BUCKET | ||
| value: louez | ||
| - key: S3_PUBLIC_URL | ||
| value: /files | ||
| - key: S3_ACCESS_KEY_ID | ||
| fromService: | ||
| type: pserv | ||
| name: louez-minio | ||
| envVarKey: MINIO_ROOT_USER | ||
| - key: S3_SECRET_ACCESS_KEY | ||
| fromService: | ||
| type: pserv | ||
| name: louez-minio | ||
| envVarKey: MINIO_ROOT_PASSWORD | ||
| dockerCommand: sh -c 'export DATABASE_URL="mysql://root:$MYSQL_PASSWORD@louez-mysql:3306/louez"; exec node apps/web/server.js' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If the password entered in Render contains URI delimiters such as Useful? React with 👍 / 👎. |
||
|
|
||
| - type: pserv | ||
| name: louez-mysql | ||
| runtime: image | ||
| plan: starter | ||
| region: frankfurt | ||
| image: | ||
| url: docker.io/library/mysql:8.4 | ||
| autoDeployTrigger: "off" | ||
| disk: | ||
| name: mysql-data | ||
| mountPath: /var/lib/mysql | ||
| sizeGB: 10 | ||
| envVars: | ||
| - key: MYSQL_ROOT_PASSWORD | ||
| # Prompted once when you launch the Blueprint. Use letters and digits | ||
| # only: the value is embedded in a connection URL. | ||
| sync: false | ||
| - key: MYSQL_DATABASE | ||
| value: louez | ||
| # MySQL refuses to initialize into a non-empty directory, and a fresh disk | ||
| # is not empty (lost+found), so the data lives one level down. | ||
| dockerCommand: mysqld --datadir=/var/lib/mysql/data | ||
|
|
||
| # MinIO with the product bucket pre-created. Render's docker command is | ||
| # passed to the image's entrypoint rather than replacing it, and MinIO's | ||
| # entrypoint prepends `minio` to whatever it receives — so the bucket step | ||
| # lives in a four-line image built from this repository instead. | ||
| - type: pserv | ||
| name: louez-minio | ||
| runtime: docker | ||
| plan: starter | ||
| region: frankfurt | ||
| dockerfilePath: ./docker/Dockerfile.minio | ||
| dockerContext: ./docker | ||
| autoDeployTrigger: "off" | ||
| disk: | ||
| name: minio-data | ||
| mountPath: /data | ||
| sizeGB: 10 | ||
| envVars: | ||
| - key: MINIO_ROOT_USER | ||
| value: louez | ||
| - key: MINIO_ROOT_PASSWORD | ||
| generateValue: true | ||
| - key: S3_BUCKET | ||
| value: louez | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a user accepts the default Heroku deployment and leaves these fields blank, the container cannot start:
apps/web/env.ts:46-50declares all five S3 settings as required URL/non-empty values, and runtime validation is enabled in the final image. Marking them optional while supplying onlyS3_PUBLIC_URLtherefore produces an environment-validation failure rather than the documented deployment with uploads disabled; either provision storage or make the application schema genuinely support missing S3 configuration.Useful? React with 👍 / 👎.