From fd9067b470edfcdb93aaefad9ed15fc70b7c14b5 Mon Sep 17 00:00:00 2001 From: Julien Nahum Date: Thu, 8 Aug 2024 16:33:01 +0200 Subject: [PATCH] 518 setup env command (#519) * Created command and cleaned * Simplified docker setup, created script to generate .env * add git ignore file back --- .env.docker | 2 +- README.md | 188 ++++++++++++++++++++++------------ client/.env.docker | 5 +- docker-compose.yml | 10 +- docker/Dockerfile.api | 2 - docker/Dockerfile.client | 1 - docker/generate-api-secret.sh | 42 -------- docker/node-entrypoint | 17 +-- docker/php-fpm-entrypoint | 66 ++---------- scripts/setup-env.sh | 88 ++++++++++++++++ storage/logs/.gitignore | 2 +- 11 files changed, 226 insertions(+), 197 deletions(-) delete mode 100644 docker/generate-api-secret.sh create mode 100755 scripts/setup-env.sh diff --git a/.env.docker b/.env.docker index 55b4bb46a..24925b695 100644 --- a/.env.docker +++ b/.env.docker @@ -12,7 +12,7 @@ FILESYSTEM_DRIVER=local BROADCAST_CONNECTION=log CACHE_STORE=redis QUEUE_CONNECTION=redis -SESSION_DRIVER=file +SESSION_DRIVER=redis SESSION_LIFETIME=120 MAIL_MAILER=log diff --git a/README.md b/README.md index 1c66d77bd..4ae1b3e21 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@

-

Github Stars @@ -25,24 +24,25 @@ ## Features -- No-code form builder, with infinite number of fields & submissions -- Text inputs, Date inputs, URL inputs, Phone inputs, Email inputs, Checkboxes, Select and Multi-Select inputs, Number Inputs, Star-ratings, File uploads & more -- Embed anywhere (on your website, in your Notion page, etc) -- Email notifications (for both form owner & form respondents) -- Hidden fields -- Form passwords -- URL form pre-fill -- Slack integration -- Webhooks -- Form logic -- Customize colors, add images or even some custom code -- Captcha form protection -- Form closing date -- Limit the number of submissions allowed +- No-code form builder, with infinite number of fields & submissions +- Text inputs, Date inputs, URL inputs, Phone inputs, Email inputs, Checkboxes, Select and Multi-Select inputs, Number Inputs, Star-ratings, File uploads & more +- Embed anywhere (on your website, in your Notion page, etc) +- Email notifications (for both form owner & form respondents) +- Hidden fields +- Form passwords +- URL form pre-fill +- Slack integration +- Webhooks +- Form logic +- Customize colors, add images or even some custom code +- Captcha form protection +- Form closing date +- Limit the number of submissions allowed And much more! ## Bounties + Get paid for contributing to OpnForm! Here are our open bounties: @@ -60,38 +60,66 @@ It takes 1 minute to try out the builder for free. You'll have high availability ### Requirements -- PHP >= 8.0 -- MySQL/MariaDB or PostgreSQL -- Node.js and NPM/Yarn/... to compile assets +- PHP >= 8.0 +- MySQL/MariaDB or PostgreSQL +- Node.js and NPM/Yarn/... to compile assets ## Installation +### Environment Setup + +Before you can run the application, you need to set up the environment variables. We have provided a script that will automate the process of creating your `.env` files from the provided examples. + +Follow these steps to set up your environment: + +1. Make sure you have `openssl` installed, as it is required by the setup script to generate secure keys. + +2. Run the setup script from the root of the project: + + ```bash + chmod +x ./scripts/setup-env.sh + ./scripts/setup-env.sh + ``` + + **If you are using Docker** and want to prepare a Docker-specific environment, run the script with the `--docker` flag: + + ```bash + ./scripts/setup-env.sh --docker + ``` + +3. After running the script, review the `.env` and `client/.env` files to ensure all settings are correct for your environment. + +Remember to never commit your `.env` files to version control. They should be kept private as they contain sensitive information. + ### Docker Installation 🐳 OpnForm can be easily set up using Docker. Pre-built images are available on Docker Hub, which is the recommended method for most users. #### Prerequisites -- Docker -- Docker Compose + +- Docker +- Docker Compose #### Quick Start 1. Clone the repository: - ``` - git clone https://github.com/JhumanJ/OpnForm.git - cd OpnForm - ``` -2. Set up environment files: - ``` - cp .env.docker .env - cp client/.env.docker client/.env - ``` + ``` + git clone https://github.com/JhumanJ/OpnForm.git + cd OpnForm + ``` + +2. Set up environment files by running the provided setup script. For detailed instructions, refer to the [Environment Setup](#environment-setup) section above: + + ```bash + ./scripts/setup-env.sh --docker + ``` 3. Start the application: - ``` - docker-compose up -d - ``` + + ``` + docker-compose up -d + ``` 4. Access OpnForm at http://localhost @@ -99,59 +127,72 @@ OpnForm can be easily set up using Docker. Pre-built images are available on Doc #### Customization -- **Environment Variables**: Modify `.env` and `client/.env` files to customize your setup. For example, to enable email features, configure a [supported mail driver](https://laravel.com/docs/11.x/mail) in the `.env` file. +- **Environment Variables**: Modify `.env` and `client/.env` files to customize your setup. For example, to enable email features, configure a [supported mail driver](https://laravel.com/docs/11.x/mail) in the `.env` file. #### Upgrading 1. Check the upgrade instructions for your target version in the documentation. 2. Update your `docker-compose.yml` file if necessary. 3. Apply changes: - ``` - docker-compose up -d - ``` + ``` + docker-compose up -d + ``` -### Initial Login +#### Initial Login After installation, use these credentials to access the admin panel: -- Email: `admin@opnform.com` -- Password: `password` + +- Email: `admin@opnform.com` +- Password: `password` ⚠️ Change these credentials immediately after your first login. Note: Public registration is disabled in the self-hosted version. Use the admin account to invite additional users. -### Building from Source +#### Building from Source For development or customization, you can build the Docker images locally: 1. Build the images: - ``` - docker build -t opnform-ui:local -f docker/Dockerfile.client . - docker build -t opnform-api:local -f docker/Dockerfile.api . - ``` + + ``` + docker build -t opnform-ui:local -f docker/Dockerfile.client . + docker build -t opnform-api:local -f docker/Dockerfile.api . + ``` 2. Create a docker-compose override file: - ``` - cp docker-compose.override.yml.example docker-compose.override.yml - ``` - - Edit the `docker-compose.override.yml` file to use your locally built images: - ```yaml - services: - api: - image: opnform-api:local - ui: - image: opnform-ui:local - ``` + + ``` + cp docker-compose.override.yml.example docker-compose.override.yml + ``` + + Edit the `docker-compose.override.yml` file to use your locally built images: + + ```yaml + services: + api: + image: opnform-api:local + ui: + image: opnform-ui:local + ``` 3. Start the application: - ``` - docker-compose up -d - ``` + ``` + docker-compose up -d + ``` This method allows you to make changes to the source code and rebuild the images as needed. +#### Clearing all resources + +To completely remove all Docker containers, networks, and volumes created by `docker-compose` and also remove all images used by these services, you can use the following command: + +```bash +docker-compose down -v --rmi all +``` + ### Using Laravel Valet + This section explains how to get started locally with the project. It's most likely relevant if you're trying to work on the project. First, let's work with the codebase and its dependencies. @@ -160,8 +201,8 @@ First, let's work with the codebase and its dependencies. git clone git@github.com:JhumanJ/OpnForm.git && cd OpnForm # Install PHP dependencies -composer install - +composer install + # Install JS dependencies cd client && npm install @@ -183,9 +224,18 @@ php artisan jwt:secret # and select yes! # Creates DB schemas php artisan migrate ``` -Now, create an S3 bucket (or equivalent). Create an IAM user with access to this bucket, fill the environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_DEFAULT_REGION`, `AWS_BUCKET`. In your AWS bucket permissions, add the following under "Cross-origin resource sharing (CORS)": + +Now, create an S3 bucket (or equivalent). Create an IAM user with access to this bucket, fill the environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_DEFAULT_REGION`, `AWS_BUCKET`. In your AWS bucket permissions, add the following under "Cross-origin resource sharing (CORS)": + ```json -[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "PUT", "POST", "GET", "DELETE" ], "AllowedOrigins": [ "*" ], "ExposeHeaders": [] } ] +[ + { + "AllowedHeaders": ["*"], + "AllowedMethods": ["PUT", "POST", "GET", "DELETE"], + "AllowedOrigins": ["*"], + "ExposeHeaders": [] + } +] ``` 🎉 Done! Enjoy your personal OpnForm instance at: [http://opnform.test](http://opnform.test). @@ -197,14 +247,16 @@ Now, create an S3 bucket (or equivalent). Create an IAM user with access to this ## Tech Stack OpnForm is a standard web application built with: -- [Laravel](https://laravel.com/) PHP framework -- [NuxtJs](https://nuxt.com/) Front-end SSR framework -- [Vue.js 3](https://vuejs.org/) Front-end framework -- [TailwindCSS](https://tailwindcss.com/) + +- [Laravel](https://laravel.com/) PHP framework +- [NuxtJs](https://nuxt.com/) Front-end SSR framework +- [Vue.js 3](https://vuejs.org/) Front-end framework +- [TailwindCSS](https://tailwindcss.com/) ## Contribute + You're more than welcome to contribute to this project. We don't have guidelines on this yet, but we will soon. In the meantime, feel free to ask [any question here](https://github.com/JhumanJ/OpnForm/discussions). ## License -OpnForm is open-source under the GNU Affero General Public License Version 3 (AGPLv3) or any later version. You can find it [here](https://github.com/JhumanJ/OpnForm/blob/main/LICENSE). +OpnForm is open-source under the GNU Affero General Public License Version 3 (AGPLv3) or any later version. You can find it [here](https://github.com/JhumanJ/OpnForm/blob/main/LICENSE). diff --git a/client/.env.docker b/client/.env.docker index a8ad68f32..21938a897 100644 --- a/client/.env.docker +++ b/client/.env.docker @@ -1,7 +1,7 @@ NUXT_LOG_LEVEL= NUXT_PUBLIC_APP_URL=/ NUXT_PUBLIC_API_BASE=/api -NUXT_PRIVATE_API_BASE=http://localhost/api +NUXT_PRIVATE_API_BASE=http://ingress/api NUXT_PUBLIC_AI_FEATURES_ENABLED=false NUXT_PUBLIC_AMPLITUDE_CODE= NUXT_PUBLIC_CRISP_WEBSITE_ID= @@ -10,5 +10,4 @@ NUXT_PUBLIC_ENV=local NUXT_PUBLIC_GOOGLE_ANALYTICS_CODE= NUXT_PUBLIC_H_CAPTCHA_SITE_KEY= NUXT_PUBLIC_PAID_PLANS_ENABLED= -NUXT_PUBLIC_S3_ENABLED=false -NUXT_API_SECRET= +NUXT_PUBLIC_S3_ENABLED=false \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index d0e75c3dc..d12906c59 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,8 +10,6 @@ services: DB_USERNAME: ${DB_USERNAME:-forge} DB_PASSWORD: ${DB_PASSWORD:-forge} DB_CONNECTION: ${DB_CONNECTION:-pgsql} - LOG_LEVEL: ${LOG_LEVEL:-debug} - LOG_CHANNEL: ${LOG_CHANNEL:-errorlog} AWS_ENDPOINT: http://minio:9000 AWS_ACCESS_KEY_ID: ${MINIO_ACCESS_KEY:-minio} AWS_SECRET_ACCESS_KEY: ${MINIO_SECRET_KEY:-minio123} @@ -23,11 +21,13 @@ services: env_file: ./.env volumes: - laravel-persist:/persist - - secrets-config:/secrets + - ./storage/logs:/usr/share/nginx/html/storage/logs api-worker: <<: *api command: ./artisan queue:work + volumes: + - ./storage/logs:/usr/share/nginx/html/storage/logs ui: image: jhumanj/opnform-client:latest @@ -38,11 +38,8 @@ services: env_file: - ./client/.env volumes: - - secrets-config:/secrets - ./client/.env:/app/.env - - redis: image: redis:7 @@ -65,4 +62,3 @@ services: volumes: laravel-persist: postgres-data: - secrets-config: diff --git a/docker/Dockerfile.api b/docker/Dockerfile.api index 318caa45d..35a65ffd8 100644 --- a/docker/Dockerfile.api +++ b/docker/Dockerfile.api @@ -40,8 +40,6 @@ RUN chmod 777 -R storage RUN php artisan package:discover --ansi COPY docker/php-fpm-entrypoint /usr/local/bin/opnform-entrypoint -COPY docker/generate-api-secret.sh /usr/local/bin/ -RUN ln -s /secrets/api.env .env RUN chmod a+x /usr/local/bin/* diff --git a/docker/Dockerfile.client b/docker/Dockerfile.client index 97930e47f..b8d68c9c1 100644 --- a/docker/Dockerfile.client +++ b/docker/Dockerfile.client @@ -26,7 +26,6 @@ FROM node:20-alpine WORKDIR /app COPY --from=javascript-builder /app/.output/ /app/ RUN ls /app/ -RUN ln -s /secrets/client.env .env ADD ./docker/node-entrypoint /entrypoint.sh RUN chmod a+x /entrypoint.sh diff --git a/docker/generate-api-secret.sh b/docker/generate-api-secret.sh deleted file mode 100644 index 7ea95ed21..000000000 --- a/docker/generate-api-secret.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -e - -main() { - generate_api_secrets -} - -generate_api_secrets() { - if ! is_configured; then - echo "Generating shared secret..." - SECRET="$(random_string)" - add_secret_to_env_file /secrets/client.env NUXT_API_SECRET "$SECRET" - add_secret_to_env_file /secrets/api.env FRONT_API_SECRET "$SECRET" - fi -} - -random_string() { - array=() - for i in {a..z} {A..Z} {0..9}; - do - array[$RANDOM]=$i - done - printf %s ${array[@]::8} $'\n' -} - -add_secret_to_env_file() { - FILE=$1 - TEMP_FILE=/tmp/env.$$ - VAR=$2 - VAL=$3 - - grep -q "^$VAR=" "$FILE" 2>/dev/null || ( echo "$VAR=" >> "$FILE" ) - - cp $FILE $TEMP_FILE - sed "s/^$VAR=.*$/$VAR=$VAL/" -i $TEMP_FILE - cat $TEMP_FILE > $FILE -} - -is_configured() { - grep -q "FRONT_API_SECRET=.\+" .env 2>/dev/null -} - -main diff --git a/docker/node-entrypoint b/docker/node-entrypoint index 7ce865c38..12eb9e0fa 100644 --- a/docker/node-entrypoint +++ b/docker/node-entrypoint @@ -1,13 +1,9 @@ #!/bin/sh main() { - if [ "$1" == "bash" ]; then + if [ "$1" = "bash" ]; then "$@" else - wait_for_api_secret - if [ ! -f .env ] && [ -f /secrets/client.env ]; then - ln -sf /secrets/client.env .env - fi if [ -f .env ]; then . .env else @@ -16,15 +12,10 @@ main() { run_server "$@" fi } -wait_for_api_secret() { - until [ -f /secrets/configured ]; do - echo "Waiting for api secret..." - sleep 1 - done -} + run_server() { - echo "Running " node "$@" + echo "Running node $@" "$@" } -main "$@" +main "$@" \ No newline at end of file diff --git a/docker/php-fpm-entrypoint b/docker/php-fpm-entrypoint index aab78ee4a..1ad0eaa9b 100644 --- a/docker/php-fpm-entrypoint +++ b/docker/php-fpm-entrypoint @@ -1,61 +1,22 @@ #!/bin/bash main() { - read_env prep_file_permissions prep_storage - if is_master "$@"; then - prep_laravel_secrets - wait_for_db - apply_db_migrations - run_init_project - mark_ready - else - wait_for_ready - wait_for_db - fi - read_env + wait_for_db + apply_db_migrations + run_init_project run_server "$@" } + is_master() { echo "$@" | grep -q php-fpm } -read_env() { - #set +x - [ -f .env ] || touch .env - . .env - #set -x -} prep_file_permissions() { chmod a+x ./artisan } -prep_laravel_secrets() { - read_env - - [ "x$APP_KEY" != "x" ] || { - echo "Generating Laravel key..." - grep -q "APP_KEY=" .env || { - echo "APP_KEY=" >> .env - } - ./artisan key:generate - read_env - } - [ "x$JWT_SECRET" != "x" ] || { - echo "Generating Laravel Secret..." - ./artisan jwt:secret -f - read_env - } - - [ "x$FRONT_API_SECRET" != "x" ] || { - echo "Generating Shared Client Secret..." - /usr/local/bin/generate-api-secret.sh - read_env - } - echo "Done with secrets" -} - apply_db_migrations() { echo "Running DB Migrations" ./artisan migrate @@ -66,28 +27,15 @@ run_init_project() { ./artisan app:init-project } -wait_for_ready() { - echo "Checking keys have been generated" - until [ -f /secrets/configured ]; do - sleep 1; - echo "Waiting for keys to generate" - done -} - -mark_ready() { - touch /secrets/configured -} - wait_for_db() { + echo "Waiting for DB to be ready" until ./artisan migrate:status 2>&1 | grep -q -E "(Migration table not found|Migration name)"; do - echo "Waiting for DB to bootup" sleep 1 done } run_server() { - echo "Booting $@" - read_env + echo "Starting server $@" /usr/local/bin/docker-php-entrypoint "$@" } @@ -112,4 +60,4 @@ prep_storage() { ln -t . -sf /persist/storage } -main "$@" +main "$@" \ No newline at end of file diff --git a/scripts/setup-env.sh b/scripts/setup-env.sh new file mode 100755 index 000000000..8b92e0d9d --- /dev/null +++ b/scripts/setup-env.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +set -e + +# Welcome to the OpnForm environment setup script! + +# Paths to the environment files +ENV_FILE=".env" +CLIENT_ENV_FILE="client/.env" + +# Paths to the environment templates +ENV_EXAMPLE=".env.example" +CLIENT_ENV_EXAMPLE="client/.env.example" + +# Check for the --docker flag to use Docker-specific environment settings +USE_DOCKER_ENV=false +for arg in "$@"; do + if [ "$arg" == "--docker" ]; then + USE_DOCKER_ENV=true + ENV_EXAMPLE=".env.docker" + CLIENT_ENV_EXAMPLE="client/.env.docker" + echo "OpnForm setup detected the --docker flag. Preparing Docker-specific environment..." + break + fi +done + +# Function to generate a random string for secrets +generate_secret() { + LC_ALL=C tr -dc A-Za-z0-9 > "$file" + fi +} + +# Check if the main .env file exists +if [ -f "$ENV_FILE" ]; then + echo "OpnForm's main .env file is already in place. No further action is needed." +else + echo "Creating OpnForm's main .env file from the template..." + cp "$ENV_EXAMPLE" "$ENV_FILE" + + # Secure your OpnForm instance with a unique APP_KEY + APP_KEY=$(generate_base64_key) + set_env_value "$ENV_FILE" "APP_KEY" "base64:$APP_KEY" + + # Generate a JWT_SECRET to sign your tokens + JWT_SECRET=$(generate_secret) + set_env_value "$ENV_FILE" "JWT_SECRET" "$JWT_SECRET" + + # Generate a shared secret for the client + SHARED_SECRET=$(generate_secret) + set_env_value "$ENV_FILE" "FRONT_API_SECRET" "$SHARED_SECRET" +fi + +# Check if the client .env file exists +if [ -f "$CLIENT_ENV_FILE" ]; then + echo "OpnForm's client .env file is already configured. Moving on..." +else + echo "Creating OpnForm's client .env file from the template..." + cp "$CLIENT_ENV_EXAMPLE" "$CLIENT_ENV_FILE" + set_env_value "$CLIENT_ENV_FILE" "NUXT_API_SECRET" "$SHARED_SECRET" +fi + +echo "✅ OpnForm environment setup is now complete. Enjoy building your forms!" \ No newline at end of file diff --git a/storage/logs/.gitignore b/storage/logs/.gitignore index d6b7ef32c..c96a04f00 100644 --- a/storage/logs/.gitignore +++ b/storage/logs/.gitignore @@ -1,2 +1,2 @@ * -!.gitignore +!.gitignore \ No newline at end of file