diff --git a/.env.development.docker.sample b/.env.development.docker.sample deleted file mode 100644 index 7026796..0000000 --- a/.env.development.docker.sample +++ /dev/null @@ -1,20 +0,0 @@ -# being used by deploy.sh on ./deploy.sh local start - -DATABASE_PASSWORD="setpasswordhere" -DATABASE_USERNAME="2a5-development" -DATABASE_NAME="2a5-development" -DATABASE_PORT=5432 -DATABASE_HOST="2a5-db-development" -DATABASE_URL="postgresql://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}" -LINK_PROTOCOL="http" -LINK_HOSTNAME="localhost" -LINK_PORT=3001 -DOCKER_WEB_HOSTNAME="2a5-web-development" -DOCKER_WEB_TARGET="runner" -DOCKER_WEB_IMAGE="2a5-web-development" -DOCKER_WEB_PORT=3001 -DOCKER_WEB_CONTAINERNAME="2a5-web-development" -DOCKER_DB_CONTAINERNAME="2a5-db-development" -DOCKER_DB_VOLUMENAME="2a5-db-data-development" -ADMIN_PORT=3002 -ADMIN_TOKEN=TZWH9HM3djMJX7y4cakk7STXQEcyVsYtRwy \ No newline at end of file diff --git a/.env.development.sample b/.env.development.sample index 244f70f..1e2e403 100644 --- a/.env.development.sample +++ b/.env.development.sample @@ -1,6 +1,4 @@ -# being used by nextjs on `npm run dev` - -DATABASE_PASSWORD="setpasswordhere" +DATABASE_PASSWORD="SET_PASSWORD_HERE" DATABASE_USERNAME="2a5-development" DATABASE_NAME="2a5-development" DATABASE_PORT=5432 @@ -8,4 +6,14 @@ DATABASE_HOST="localhost" DATABASE_URL="postgresql://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}" LINK_PROTOCOL="http" LINK_HOSTNAME="localhost" -LINK_PORT=3001 \ No newline at end of file +LINK_PORT=3001 +ADMIN_TOKEN="SET_TOKEN_HERE" +ADMIN_PORT=3002 +DOCKER_API_HOSTNAME="2a5-api-development" +DOCKER_API_TARGET="runner" +DOCKER_API_IMAGE="2a5-api-development" +DOCKER_API_PORT=3000 +DOCKER_API_CONTAINERNAME="2a5-api-development" +DOCKER_DB_CONTAINERNAME="2a5-db-development" +DOCKER_DB_VOLUMENAME="2a5-db-data-development" +DOCKER_DB_HOSTNAME="2a5-db-development" \ No newline at end of file diff --git a/.env.prod.docker.sample b/.env.prod.docker.sample deleted file mode 100644 index 9c0ee71..0000000 --- a/.env.prod.docker.sample +++ /dev/null @@ -1,16 +0,0 @@ -DATABASE_PASSWORD="setpasswordhere" -DATABASE_USERNAME="2a5-prod" -DATABASE_NAME="2a5-prod" -DATABASE_PORT=5433 -DATABASE_HOST="2a5-db-prod" -DATABASE_URL="postgresql://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}" -DOCKER_WEB_HOSTNAME="2a5-web-prod" -DOCKER_WEB_TARGET="runnerBuild" -DOCKER_WEB_IMAGE="2a5-web-prod" -DOCKER_WEB_PORT=8082 -DOCKER_WEB_CONTAINERNAME="2a5-web-prod" -DOCKER_DB_CONTAINERNAME="2a5-db-prod" -DOCKER_DB_VOLUMENAME="2a5-db-data-prod" -LINK_PROTOCOL="https" -LINK_HOSTNAME="2a5.de" -# LINK_PORT="" # is not set here so that short links do not have a port defined - but could do so if needed diff --git a/.env.test.docker.sample b/.env.test.docker.sample deleted file mode 100644 index bb371f8..0000000 --- a/.env.test.docker.sample +++ /dev/null @@ -1,16 +0,0 @@ -DATABASE_PASSWORD="setpasswordhere" -DATABASE_USERNAME="2a5-test" -DATABASE_NAME="2a5-test" -DATABASE_PORT=5432 -DATABASE_HOST="2a5-db-test" -DATABASE_URL="postgresql://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}" -DOCKER_WEB_HOSTNAME="2a5-web-test" -DOCKER_WEB_TARGET="runnerBuild" -DOCKER_WEB_IMAGE="2a5-web-test" -DOCKER_WEB_PORT=8081 -DOCKER_WEB_CONTAINERNAME="2a5-web-test" -DOCKER_DB_CONTAINERNAME="2a5-db-test" -DOCKER_DB_VOLUMENAME="2a5-db-data-test" -LINK_PROTOCOL="https" -LINK_HOSTNAME="test.2a5.de" -# LINK_PORT="" # is not set here so that short links do not have a port defined - but could do so if needed diff --git a/README.md b/README.md index 864e932..59bf1b7 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ You need to install on your local workstation: Clone the repository: ```bash -git clone https://github.com/reckseba/2a5.git +git clone https://github.com/reckseba/2a5-api.git ``` Install your environment @@ -46,7 +46,7 @@ npm run prismagenerate Push the database schema to postgres (only on first start when docker volume is initially created) ```bash -npm run prismadbpush +npm run prismamigratedev ``` Run the nodejs development server: @@ -85,23 +85,21 @@ npm run lint # Deploy Development (locally) This runs the environment on docker. It does not support hot reload. -Prepare your local config: +Prepare your local config (if not done already): ```bash -cp ./.env.development.docker.sample ./.env.development.docker.local +cp ./.env.development.sample ./.env.development.local ``` +Do changes in ./.env.development.local now. -Put same db password like in `.env.development.local` -```bash -vim ./.env.development.docker.local -``` -Start the web and db containers +Start the api and db containers ```bash -./deploy.sh development start +docker compose --env-file ./.env.development.local up -d ``` -Push the database schema to postgres (only if not done before on first start when docker volume is initially created) +Push the database schema to postgres (only if not done before on first start when docker volume is initially created). ```bash +npm install npm run prismamigratedeploy ``` @@ -111,59 +109,16 @@ __Warning__: This command truncates your table content! npm run test ``` -Stop the web and db containers -```bash -./deploy.sh development stop -``` - -Restart the web and db containers -```bash -./deploy.sh development restart -``` - -# Create SSH Config - -Your ~/.ssh/config file should include a section such as: -```bash -Host servername - HostName 1.2.3.4 - User yourusername - IdentityFile ~/.ssh/privatekeyfile -``` - -# Security Considerations - -You could launch this API twice -- One public facing for the Client-APP with high restrictions on the database -- The other in private not being exposed to the public with a little more rights to facilitate the admin operations. - -# Deploy Test -This builds, takes the increment, uploads it and runs it in docker on the server. - -Prepare your local config -```bash -cp ./.env.test.docker.sample ./.env.test.docker.local -vim ./.env.test.local -``` - -This will build the Dockerfile until the builder stage. Then it runs a docker container named `2a5-build` from which the deployment script will copy the build increments. Finally it copies the build to your remote location, unpacks and runs it via docker compose. At last it migrates the latest database schema to the postgres instance. +Stop the api and db containers ```bash -./deploy.sh test build servername -``` - -The following command stops the remote containers and deletes the directory `build`. -```bash -./deploy.sh test clean servername +docker compose --env-file ./.env.development.local down ``` -If you want to remove images and volumes, have a look at the Cleanup remote section. - # Cleanup locally Delete all generated files ```bash rm -rf .next/ node_modules/ next-env.d.ts cypress/screenshots/ cypress/videos/ - ``` If you want to delete your docker postgres image (volume with database entries remains) ```bash @@ -185,15 +140,6 @@ DANGER! Erases all images docker image prune -a ``` -# Cleanup remote test +# Deployment to test/staging/production systems -Remove the volume -```bash -docker volume rm 2a5-db-data-test -``` - -Remove used images -```bash -docker image rm 2a5-web-test:latest -docker image rm postgres:14-alpine -``` +Checkout 2a5-deploy repository. \ No newline at end of file diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index e3f1bba..0000000 --- a/deploy.sh +++ /dev/null @@ -1,187 +0,0 @@ -#!/bin/bash - -if [ $# -eq 0 ] -then - echo "Please define an environment (development|test|prod) as first argument." - exit 1 -fi - -if [ $# -eq 1 ] -then - echo "Please define mode for environemnt as second argument." - exit 1 -fi - -if [ $# -eq 2 ] && [ $1 != "development" ] -then - echo "Two arguments are only allowed for environment development." - exit 1 -fi - -if [ $# -eq 3 ] && [ $1 != "test" ] && [ $1 != "prod" ] -then - echo "Three arguments are only allowed for environments test or prod." - exit 1 -fi - -ENV=$1 -MODE=$2 -SERVER=$3 - -echo "Deploy for $ENV" - -stop_server () { - - if [[ $(docker compose ls -q) == "2a5-api" ]] - then - echo "I'll shut down the runnning docker compose project..." - docker compose --env-file ./.env.development.docker.local down - else - echo "There is no docker compose project running. I'll do nothing and exit." - fi -} - -start_server () { - - if [[ $(docker compose ls -q) == "2a5-api" ]] - then - echo "There is a docker compose project runnning still. I'll do nothing and exit." - else - echo "I'll start the docker compose project now..." - docker compose --env-file ./.env.development.docker.local build --no-cache - docker compose --env-file ./.env.development.docker.local up -d - fi -} - -restart_server () { - - stop_server - start_server - -} - -if [ $ENV == "development" ] -then - - if [ $MODE == "start" ] - then - - start_server - exit 0 - - elif [ $MODE == "stop" ] - then - - stop_server - exit 0 - - elif [ $MODE == "restart" ] - then - - restart_server - exit 0 - - elif [ $MODE == "clean" ] - then - - docker volume rm 2a5_db-data - exit 0 - - else - - echo "Please define mode for development (start|stop|restart|clean)" - - fi - -elif ( [ $ENV == "test" ] || [ $ENV == "prod" ] ) -then - - if [ $MODE == "build" ] - then - - rm -rf build/ - mkdir -p build/ - - # check if docker container still running - if [[ $(docker compose ls -q) == "2a5-build" ]] - then - docker stop 2a5-build - fi - - # targets the builder stage and stops there - does not run node server inside - docker build --no-cache -f Dockerfile --target builder -t 2a5-build . - - # -i argument to keep open - docker run --rm -d -i --name 2a5-build 2a5-build - - # copy build increments from docker container - docker cp 2a5-build:/app/.next/standalone/. ./build - - # from the documentation: https://nextjs.org/docs/advanced-features/output-file-tracing - # Additionally, a minimal server.js file is also output which can be used instead of next start. - # This minimal server does not copy the public or .next/static folders by default as these should - # ideally be handled by a CDN instead, although these folders can be copied to the standalone/public - # and standalone/.next/static folders manually, after which server.js file will serve these automatically. - docker cp 2a5-build:/app/.next/static/. ./build/.next/static - - # copy new schema - docker cp 2a5-build:/app/prisma/. ./build/prisma - # cp -r prisma build/prisma - - # need to stop it due to -i on run - docker stop 2a5-build - - # not being copied on build - cp -r public build/public - - # copy config - cp .env.$ENV.docker.local build/.env - - # bundle the files we need - tar -cvf build.tar build - - # append the bundle - tar -rvf build.tar docker-compose.yml Dockerfile - - # cleanup locally - rm -rf build/ - - # secure copy to our remote location - scp build.tar $SERVER:. - - # remove local bundle - rm build.tar - - # check if containers are running - #ssh $SERVER "docker compose --env-file ./build/.env down" - - # stop the running containers - ssh $SERVER "docker compose --env-file ./build/.env down" - ssh $SERVER "rm -rf build" - ssh $SERVER "tar -xvf build.tar" - ssh $SERVER "rm build.tar" - ssh $SERVER "docker compose --env-file ./build/.env build --no-cache" - ssh $SERVER "docker compose --env-file ./build/.env up -d" - ssh $SERVER "docker ps" - - # deploy the prisma db schema changes - ssh $SERVER "docker exec 2a5-web-$ENV npx prisma migrate deploy" - - exit 0 - - elif [ $MODE == "clean" ] - then - - ssh $SERVER "docker compose --env-file ./build/.env down" - ssh $SERVER "rm -rf build" - ssh $SERVER "rm Dockerfile docker-compose.yml" - - fi - -else - - echo "Please define an environment (development|test|prod)" - - exit 1 - -fi diff --git a/docker-compose.yml b/docker-compose.yml index 58bd21f..3f88dc9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ services: logging: driver: "none" restart: unless-stopped - hostname: ${DATABASE_HOST} + hostname: ${DOCKER_DB_HOSTNAME} volumes: - db-data:/var/lib/postgresql/data ports: diff --git a/prisma/migrations/20240329122701_init/migration.sql b/prisma/migrations/20240329122701_init/migration.sql new file mode 100644 index 0000000..addc548 --- /dev/null +++ b/prisma/migrations/20240329122701_init/migration.sql @@ -0,0 +1,65 @@ +-- CreateEnum +CREATE TYPE "CheckType" AS ENUM ('ADMIN', 'WHITELIST', 'BLACKLIST'); + +-- CreateTable +CREATE TABLE "Urls" ( + "id" SERIAL NOT NULL, + "urlLong" TEXT NOT NULL, + "urlQrCode" TEXT NOT NULL, + "urlShort" TEXT NOT NULL, + "urlShortFull" TEXT NOT NULL, + "hostname" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" BOOLEAN NOT NULL DEFAULT false, + "deletedAt" TIMESTAMP(3), + "checkedBy" "CheckType", + "checkedAt" TIMESTAMP(3), + "ipAddressHash" TEXT, + + CONSTRAINT "Urls_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Hostnames" ( + "id" SERIAL NOT NULL, + "hostname" TEXT NOT NULL, + "blacklisted" BOOLEAN NOT NULL DEFAULT true, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Hostnames_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Ipaddresses" ( + "id" SERIAL NOT NULL, + "ipAddressHash" TEXT NOT NULL, + "blacklisted" BOOLEAN NOT NULL DEFAULT true, + "until" TIMESTAMP(3) NOT NULL DEFAULT NOW() + interval '1 day', + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Ipaddresses_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Urls_urlLong_key" ON "Urls"("urlLong"); + +-- CreateIndex +CREATE UNIQUE INDEX "Urls_urlShort_key" ON "Urls"("urlShort"); + +-- CreateIndex +CREATE INDEX "Urls_urlLong_idx" ON "Urls"("urlLong"); + +-- CreateIndex +CREATE INDEX "Urls_urlShort_idx" ON "Urls"("urlShort"); + +-- CreateIndex +CREATE UNIQUE INDEX "Hostnames_hostname_key" ON "Hostnames"("hostname"); + +-- CreateIndex +CREATE INDEX "Hostnames_hostname_idx" ON "Hostnames"("hostname"); + +-- CreateIndex +CREATE UNIQUE INDEX "Ipaddresses_ipAddressHash_key" ON "Ipaddresses"("ipAddressHash"); + +-- CreateIndex +CREATE INDEX "Ipaddresses_ipAddressHash_idx" ON "Ipaddresses"("ipAddressHash"); diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..fbffa92 --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file