Add EasyPanel Template for OpnForm with 1-Click Deploy Button
Add EasyPanel Template for OpnForm with 1-Click Deploy Button
Weβd love to have an EasyPanel template for OpnForm, our open-source form builder. The goal is to enable users to deploy OpnForm with a single click through EasyPanel.
Background:
OpnForm already has a working Docker setup, which you can find in our deployment documentation. The Docker configuration includes everything needed for running the application. The primary task for this issue is to adapt the Docker setup for EasyPanel and create a 1-click deploy button.
Deliverables:
-
EasyPanel Template: A template that adapts the existing Docker setup to EasyPanel.
- Ensure the template includes the necessary environment variables, Docker images, and services.
- Guidance for contributing the template can be found in the EasyPanel template contribution documentation.
-
.env File Generator Script: A script (or modifications to the current one) that generates
.envfiles based on the EasyPanel deployment setup. Currently, we use scripts/setup-env.sh, but we likely need to adapt or create an equivalent script for EasyPanel. -
1-Click Deploy Button:
- Create a 1-click deploy button that integrates with EasyPanel and simplifies the deployment process for OpnForm users. Add mention to this new deployment option (and button) in the
docs.
- Create a 1-click deploy button that integrates with EasyPanel and simplifies the deployment process for OpnForm users. Add mention to this new deployment option (and button) in the
-
Merge Request to EasyPanel Repository:
- Submit the template to the EasyPanel repository following their contribution guidelines.
Resources:
Skills Required:
- Familiarity with Docker and Docker Compose.
- Experience with EasyPanel templates and deployment.
- Ability to script and automate environment variable setup.
If you have any questions or need clarification on this issue, feel free to comment below! π
Thank you for contributing to OpnForm!
/bounty 100
π $100 bounty β’ OpnForm
Steps to solve:
- Start working: Comment
/attempt #627with your implementation plan - Submit work: Create a pull request including
/claim #627in the PR body to claim the bounty - Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts
Thank you for contributing to JhumanJ/OpnForm!
Add a bounty β’ Share on socials
| Attempt | Started (GMT+0) | Solution |
|---|---|---|
| π΄ @ibishal | Dec 5, 2024, 9:31:22 AM | WIP |
/attempt #627 can i get assigned
| Algora profile | Completed bounties | Tech | Active attempts | Options |
|---|---|---|---|---|
| @ibishal | 2 bounties from 2 projects | TypeScript, Scala, Rust |
Cancel attempt |
Hey @ibishal are you comfortable doing this? If so then yes - please read the full issue!
Hey @ibishal are you comfortable doing this? If so then yes - please read the full issue!
will complete this by EOD !
Sounds good! Please note that you need to submit the template to the EasyPanel repository following their contribution guidelines, thanks!
Opened a pr at easypanel repo(https://github.com/easypanel-io/templates/pull/634)
Hey @ibishal thanks for this? Does it work for you? I tried on my easypanel instance to use the schema generated but it failed: back-end seem stuck on "Waiting for DB to be ready". Although front-end seem to work
Also can we automatically assign a URL to the project on creation?
Actually i dont have any VPS so i could not test on easypanel instance but i have test similar step on docker, it works
try with this index.ts
import {
Output,
randomPassword,
randomString,
Services,
} from "~templates-utils";
import { Input } from "./meta";
export function generate(input: Input): Output {
const services: Services = [];
const appKey = Buffer.from(randomString(32)).toString("base64");
const databasePassword = randomPassword();
const jwtSecret = randomString(40);
const sharedSecret = randomString(40);
const apiEnvironment = [
`APP_NAME=OpnForm`,
`APP_ENV=production`,
`APP_KEY=base64:${appKey}`,
`APP_DEBUG=false`,
`APP_URL=https://$(PRIMARY_DOMAIN)`,
`DB_HOST=$(PROJECT_NAME)_${input.databaseServiceName}`,
`REDIS_HOST=$(PROJECT_NAME)_${input.redisServiceName}`,
`DB_DATABASE=$(PROJECT_NAME)`,
`DB_USERNAME=postgres`,
`DB_PASSWORD=${databasePassword}`,
`DB_CONNECTION=pgsql`,
`FILESYSTEM_DISK=local`,
`LOCAL_FILESYSTEM_VISIBILITY=public`,
`JWT_SECRET=${jwtSecret}`,
`FRONT_API_SECRET=${sharedSecret}`,
].join("\n");
services.push({
type: "postgres",
data: {
serviceName: input.databaseServiceName,
password: databasePassword,
command: "",
},
});
services.push({
type: "redis",
data: {
serviceName: input.redisServiceName,
},
});
services.push({
type: "app",
data: {
serviceName: input.apiServiceName,
env: apiEnvironment,
source: {
type: "image",
image: input.apiServiceImage,
},
mounts: [
{
type: "volume",
name: "opnform-storage",
mountPath: "/usr/share/nginx/html/storage",
},
],
},
});
services.push({
type: "app",
data: {
serviceName: input.workerServiceName,
env: apiEnvironment + "\nIS_API_WORKER=true",
source: {
type: "image",
image: input.apiServiceImage,
},
mounts: [
{
type: "volume",
name: "opnform-storage",
mountPath: "/usr/share/nginx/html/storage",
},
],
},
});
services.push({
type: "app",
data: {
serviceName: input.uiServiceName,
env: [
`NUXT_PUBLIC_APP_URL=/`,
`NUXT_PUBLIC_API_BASE=/api`,
`NUXT_API_SECRET=${sharedSecret}`,
].join("\n"),
source: {
type: "image",
image: input.uiServiceImage,
},
},
});
services.push({
type: "app",
data: {
serviceName: input.ingressServiceName,
source: {
type: "image",
image: "nginx:1",
},
domains: [
{
host: "$(EASYPANEL_DOMAIN)",
port: 80,
},
],
},
});
return { services };
}
How should I try this? I used the schema generated in this comment https://github.com/easypanel-io/templates/pull/634#issuecomment-2520553093
https://deploy-preview-634--easypanel-templates.netlify.app/opnform
can you try with this schema
{
"services": [
{
"type": "app",
"data": {
"serviceName": "opnform-api",
"env": "APP_NAME=OpnForm\nAPP_ENV=production\nAPP_KEY=base64:YzRlMzU3MTdhMDVmNWQ3ZTE5M2Q5YWQyYjBlNDZmN2Q=\nAPP_DEBUG=false\nAPP_URL=https://$(PRIMARY_DOMAIN)\nDB_HOST=$(PROJECT_NAME)_opnform-db\nREDIS_HOST=$(PROJECT_NAME)_opnform-redis\nDB_DATABASE=$(PROJECT_NAME)\nDB_USERNAME=postgres\nDB_PASSWORD=ef5dbb0b00e656a677ec\nDB_CONNECTION=pgsql\nFILESYSTEM_DISK=local\nLOCAL_FILESYSTEM_VISIBILITY=public\nJWT_SECRET=a0b4810e002e9c65725f56cb15dcab14b13b544a\nFRONT_API_SECRET=bef4d24d2124b4c01f5f405c31c4da72406b7252",
"source": {
"type": "image",
"image": "jhumanj/opnform-api:1.4.5"
},
"mounts": [
{
"type": "volume",
"name": "opnform-storage",
"mountPath": "/usr/share/nginx/html/storage"
}
]
}
},
{
"type": "app",
"data": {
"serviceName": "opnform-ui",
"env": "NUXT_PUBLIC_APP_URL=https://$(PRIMARY_DOMAIN)\nNUXT_PUBLIC_API_BASE=https://$(PRIMARY_DOMAIN)/api\nNUXT_API_SECRET=bef4d24d2124b4c01f5f405c31c4da72406b7252\nNUXT_PUBLIC_ENV=dev",
"source": {
"type": "image",
"image": "jhumanj/opnform-client:1.4.5"
}
}
},
{
"type": "app",
"data": {
"serviceName": "opnform-ingress",
"env": "UI_HOST=$(PROJECT_NAME)_opnform-ui\nAPI_HOST=$(PROJECT_NAME)_opnform-api",
"source": {
"type": "image",
"image": "nginx:1.25"
},
"domains": [
{
"host": "$(EASYPANEL_DOMAIN)",
"port": 80
}
],
"deploy": {
"command": "envsubst '$UI_HOST $API_HOST' < /etc/nginx/conf.d/vhost.template > /etc/nginx/conf.d/default.conf && nginx -g \"daemon off;\""
},
"mounts": [
{
"type": "file",
"content": "\nserver {\n listen 80;\n server_name _;\n\n access_log /dev/stdout;\n error_log /dev/stderr error;\n\n location / {\n proxy_pass http://${UI_HOST}:3000;\n proxy_http_version 1.1;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-Host $host;\n proxy_set_header X-Forwarded-Port $server_port;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"Upgrade\";\n }\n\n location ~/(api|open|local\\/temp|forms\\/assets)/ {\n try_files $uri $uri/ /index.php?$query_string;\n }\n\n location ~ \\.php$ {\n fastcgi_split_path_info ^(.+\\.php)(/.+)$;\n fastcgi_pass ${API_HOST}:9000;\n fastcgi_index index.php;\n include fastcgi_params;\n fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html/public/index.php;\n fastcgi_param PATH_INFO $fastcgi_path_info;\n }\n}",
"mountPath": "/etc/nginx/conf.d/vhost.template"
}
]
}
},
{
"type": "app",
"data": {
"serviceName": "opnform-worker",
"env": "APP_NAME=OpnForm\nAPP_ENV=production\nAPP_KEY=base64:YzRlMzU3MTdhMDVmNWQ3ZTE5M2Q5YWQyYjBlNDZmN2Q=\nAPP_DEBUG=false\nAPP_URL=https://$(PRIMARY_DOMAIN)\nDB_HOST=$(PROJECT_NAME)_opnform-db\nREDIS_HOST=$(PROJECT_NAME)_opnform-redis\nDB_DATABASE=$(PROJECT_NAME)\nDB_USERNAME=postgres\nDB_PASSWORD=ef5dbb0b00e656a677ec\nDB_CONNECTION=pgsql\nFILESYSTEM_DISK=local\nLOCAL_FILESYSTEM_VISIBILITY=public\nJWT_SECRET=a0b4810e002e9c65725f56cb15dcab14b13b544a\nFRONT_API_SECRET=bef4d24d2124b4c01f5f405c31c4da72406b7252\nIS_API_WORKER=true",
"source": {
"type": "image",
"image": "jhumanj/opnform-api:1.4.5"
},
"mounts": [
{
"type": "volume",
"name": "opnform-storage",
"mountPath": "/usr/share/nginx/html/storage"
}
]
}
},
{
"type": "redis",
"data": {
"serviceName": "opnform-redis"
}
},
{
"type": "postgres",
"data": {
"serviceName": "opnform-db",
"password": "ef5dbb0b00e656a677ec"
}
}
]
}
cc @JhumanJ
Still not working unfortunately
@ibishal: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then π
I tried this template and it is solid, but there are errors:
- in the opnform-api service, the error "Waiting for DB to be ready" is received, this is because the DB is not initialized, and not because the variable APP_URL=https://$(PRIMARY_DOMAIN) is not good, this $(PRIMARY_DOMAIN is refers to the primary domain of the service, not the entire application, so when you enter the container it says that APP_URL=https:// To begin with, you need to manually replace and put the domain from the opnform-ingress service, https://example-domain.com, after this correction the app will start
- The UI is up, but there is also an error ERR_NAME_NOT_RESOLVED https://api/templates?limit=10 in the console, which indicates that the ENV values ββin the opnform-ui service are not good. it should be instead of NUXT_PUBLIC_APP_URL=https://$(PRIMARY_DOMAIN) NUXT_PUBLIC_API_BASE=https://$(PRIMARY_DOMAIN)/api put the domain from the opnform-ingress service instead of $(PRIMARY_DOMAIN), e.g. https://example-domain.com , now the address is obtained in the console as it should be, but now I get an error of the https://example-domain.com/api/register 502 (Bad Gateway)
- now I assume that the /etc/nginx/conf.d/vhost.template file of the opnform-ingress service is not good, but I have not been able to get it to work, When I try to curl from the opnform-ingress container service curl http://API_HOST:9000 I get : curl: (56) Recv failure: Connection reset by peer
I have progress, now at least I got to API container, but in it I get "GET /index.php" 404 So, NGINX forwards requests. But when I include APP_DEBUG=true in the API container
and I type in the browser https://<example-domain.com>/api/fonts/ I get an error: "The route api/fonts could not be found."
As if in the API container I have an extra prefix api/ on my route?
The bounty is up for grabs! Everyone is welcome to /attempt #627 π
I have progress, now at least I got to API container, but in it I get "GET /index.php" 404 So, NGINX forwards requests. But when I include APP_DEBUG=true in the API container
and I type in the browser https://<example-domain.com>/api/fonts/ I get an error: "The route api/fonts could not be found."
As if in the API container I have an extra prefix api/ on my route?
so are you doing the above ?
Yes, I partially described the process here. I did several things, including php artisan migrate --force in the API container to initialize the DB. I'll be able to reproduce it again, but right now I'm running into a problem that I'm getting requests in the API container from nginx from the opnform-ingress container service, but apparently I'm getting them on the wrong route. Here I need advice from someone who has a better understanding of app architecture, what's going on...
https://github.com/easypanel-io/templates/pull/956