diff --git a/.devcontainer/.gitignore b/.devcontainer/.gitignore deleted file mode 100644 index 6bf3b5d9e5..0000000000 --- a/.devcontainer/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -library \ No newline at end of file diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index b214a91729..0000000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -ARG BASEIMAGE=mcr.microsoft.com/devcontainers/typescript-node:22@sha256:a20b8a3538313487ac9266875bbf733e544c1aa2091df2bb99ab592a6d4f7399 -FROM ${BASEIMAGE} - -# Flutter SDK -# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux -ENV FLUTTER_CHANNEL="stable" -ENV FLUTTER_VERSION="3.29.1" -ENV FLUTTER_HOME=/flutter -ENV PATH=${PATH}:${FLUTTER_HOME}/bin - -# Flutter SDK -RUN mkdir -p ${FLUTTER_HOME} \ - && curl -C - --output flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/${FLUTTER_CHANNEL}/linux/flutter_linux_${FLUTTER_VERSION}-${FLUTTER_CHANNEL}.tar.xz \ - && tar -xf flutter.tar.xz --strip-components=1 -C ${FLUTTER_HOME} \ - && rm flutter.tar.xz \ - && chown -R 1000:1000 ${FLUTTER_HOME} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 2d567f033a..2a63c69be7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,26 +1,66 @@ { - "name": "Immich", - "service": "immich-devcontainer", - "dockerComposeFile": [ - "docker-compose.yml", - "../docker/docker-compose.dev.yml" - ], + "name": "Immich - Backend and Frontend", + "service": "immich-devcontainer-server", + "dockerComposeFile": ["server/docker-compose.yml"], "customizations": { "vscode": { "extensions": [ - "Dart-Code.dart-code", - "Dart-Code.flutter", "dbaeumer.vscode-eslint", - "dcmdev.dcm-vscode-extension", "esbenp.prettier-vscode", - "svelte.svelte-vscode" + "svelte.svelte-vscode", + "ms-vscode-remote.remote-containers", + "foxundermoon.shell-format", + "timonwong.shellcheck", + "rvest.vs-code-prettier-eslint", + "bluebrown.yamlfmt", + "vkrishna04.cspell-sync", + "vitest.explorer", + "ms-playwright.playwright" ] } }, - "forwardPorts": [], - "initializeCommand": "bash .devcontainer/scripts/initializeCommand.sh", - "onCreateCommand": "bash .devcontainer/scripts/onCreateCommand.sh", + "forwardPorts": [3000, 9231, 9230, 2283], + "portsAttributes": { + "3000": { + "label": "Immich - Frontend HTTP", + "description": "The frontend of the Immich project", + "onAutoForward": "openBrowserOnce" + }, + "2283": { + "label": "Immich - API Server - HTTP", + "description": "The API server of the Immich project" + }, + "9231": { + "label": "Immich - API Server - DEBUG", + "description": "The API server of the Immich project" + }, + "9230": { + "label": "Immich - Workers - DEBUG", + "description": "The workers of the Immich project" + } + }, "overrideCommand": true, - "workspaceFolder": "/immich", - "remoteUser": "node" + "workspaceFolder": "/workspaces/immich", + "remoteUser": "node", + "postCreateCommand": "/immich-devcontainer/postCreate.sh", + "userEnvProbe": "loginInteractiveShell", + "remoteEnv": { + // The location where your uploaded files are stored + // If this starts with / or ./, it is a bind mount to a path + // on host. Otherwise, it must be the value "vol-upload" + // which is also the default loaded from .env. + "UPLOAD_LOCATION": "${localEnv:UPLOAD_LOCATION}", + // The location where your database files are stored. + // If this starts with / or ./, it is a bind mount to a path + // on host. Otherwise, it must be the value "vol-database" + // which is also the default loaded from .env. + "DB_DATA_LOCATION": "${localEnv:DB_DATA_LOCATION}", + // Connection secret for postgres. You should change it to a random password + // Please use only the characters `A-Za-z0-9`, without special characters or spaces + "DB_PASSWORD": "${localEnv:DB_PASSWORD}", + // The database username + "DB_USERNAME": "${localEnv:DB_USERNAME}", + // The database name + "DB_DATABASE_NAME": "${localEnv:DB_DATABASE_NAME}" + } } diff --git a/.devcontainer/ml/.env b/.devcontainer/ml/.env new file mode 100644 index 0000000000..ac973c1275 --- /dev/null +++ b/.devcontainer/ml/.env @@ -0,0 +1,19 @@ +# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables + +# The location where your uploaded files are stored +UPLOAD_LOCATION=upload-volume + +# The location where your database files are stored +DB_DATA_LOCATION=db-volume + +# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List +# TZ=Etc/UTC + +# Connection secret for postgres. You should change it to a random password +# Please use only the characters `A-Za-z0-9`, without special characters or spaces +DB_PASSWORD=postgres + +# The values below this line do not need to be changed +################################################################################### +DB_USERNAME=postgres +DB_DATABASE_NAME=immich diff --git a/.devcontainer/ml/devcontainer.json b/.devcontainer/ml/devcontainer.json new file mode 100644 index 0000000000..3a60264d87 --- /dev/null +++ b/.devcontainer/ml/devcontainer.json @@ -0,0 +1,17 @@ +{ + "name": "Immich - Machine Learning", + "service": "immich-machine-learning", + "dockerComposeFile": ["docker-compose.yml"], + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python","ms-python.debugpy","KevinRose.vsc-python-indent" + ] + } + }, + "forwardPorts": [], + "overrideCommand": true, + "workspaceFolder": "/workspaces/immich", + "remoteUser": "node" + +} diff --git a/.devcontainer/ml/docker-compose.yml b/.devcontainer/ml/docker-compose.yml new file mode 100644 index 0000000000..314705afc9 --- /dev/null +++ b/.devcontainer/ml/docker-compose.yml @@ -0,0 +1,15 @@ +services: + immich-machine-learning: + image: immich-machine-learning-dev:latest + build: + context: ../../machine-learning + dockerfile: Dockerfile + target: devcontainer + hostname: immich-machine-learning + volumes: + # bind mount host to /workspaces/immich + - ../..:/workspaces/immich + - model-cache:/cache + +volumes: + model-cache: diff --git a/.devcontainer/mobile/.env b/.devcontainer/mobile/.env new file mode 100644 index 0000000000..ac973c1275 --- /dev/null +++ b/.devcontainer/mobile/.env @@ -0,0 +1,19 @@ +# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables + +# The location where your uploaded files are stored +UPLOAD_LOCATION=upload-volume + +# The location where your database files are stored +DB_DATA_LOCATION=db-volume + +# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List +# TZ=Etc/UTC + +# Connection secret for postgres. You should change it to a random password +# Please use only the characters `A-Za-z0-9`, without special characters or spaces +DB_PASSWORD=postgres + +# The values below this line do not need to be changed +################################################################################### +DB_USERNAME=postgres +DB_DATABASE_NAME=immich diff --git a/.devcontainer/mobile/Dockerfile b/.devcontainer/mobile/Dockerfile new file mode 100644 index 0000000000..ddd7891a6d --- /dev/null +++ b/.devcontainer/mobile/Dockerfile @@ -0,0 +1,31 @@ +ARG BASEIMAGE=ghcr.io/immich-app/base-server-dev:202503182202@sha256:45ae044b64a7b518f8d94fa4de718090c1c7689d516ac2ac0976a5331eaeb396 +FROM ${BASEIMAGE} AS dev + +# Flutter SDK +# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux +ENV FLUTTER_CHANNEL="stable" +ENV FLUTTER_VERSION="3.29.2" +ENV FLUTTER_HOME=/flutter +ENV PATH=${PATH}:${FLUTTER_HOME}/bin + +RUN apt-get install inetutils-ping sudo +RUN usermod -aG sudo node +RUN echo "node ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers +RUN mkdir -p /workspaces/immich +RUN chown node -R /workspaces + +# Flutter SDK +RUN mkdir -p ${FLUTTER_HOME} \ + && curl -C - --output flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/${FLUTTER_CHANNEL}/linux/flutter_linux_${FLUTTER_VERSION}-${FLUTTER_CHANNEL}.tar.xz \ + && tar -xf flutter.tar.xz --strip-components=1 -C ${FLUTTER_HOME} \ + && rm flutter.tar.xz \ + && chown -R node ${FLUTTER_HOME} + +USER node +RUN sudo apt-get update \ + && wget -qO- https://dcm.dev/pgp-key.public | sudo gpg --dearmor -o /usr/share/keyrings/dcm.gpg \ + && echo 'deb [signed-by=/usr/share/keyrings/dcm.gpg arch=amd64] https://dcm.dev/debian stable main' | sudo tee /etc/apt/sources.list.d/dart_stable.list \ + && sudo apt-get update \ + && sudo apt-get install dcm -y + +RUN dart --disable-analytics \ No newline at end of file diff --git a/.devcontainer/mobile/devcontainer.json b/.devcontainer/mobile/devcontainer.json new file mode 100644 index 0000000000..a7c20f6189 --- /dev/null +++ b/.devcontainer/mobile/devcontainer.json @@ -0,0 +1,20 @@ +{ + "name": "Immich - Mobile", + "service": "immich-mobile", + "dockerComposeFile": ["docker-compose.yml"], + "customizations": { + "vscode": { + "extensions": [ + "Dart-Code.dart-code", + "Dart-Code.flutter", + "dcmdev.dcm-vscode-extension", + "esbenp.prettier-vscode" + ] + } + }, + "forwardPorts": [], + "overrideCommand": true, + "workspaceFolder": "/workspaces/immich", + "remoteUser": "node", + "postCreateCommand": "/workspaces/immich/.devcontainer/mobile/postCreate.sh" +} diff --git a/.devcontainer/mobile/docker-compose.yml b/.devcontainer/mobile/docker-compose.yml new file mode 100644 index 0000000000..ac8970da08 --- /dev/null +++ b/.devcontainer/mobile/docker-compose.yml @@ -0,0 +1,27 @@ +services: + immich-mobile: + build: + dockerfile: Dockerfile + hostname: immich-devcontainer-mobile + extra_hosts: + - 'host.docker.internal:host-gateway' + volumes: + # by default, bind mount host to /workspaces/immich + - ../..:/workspaces/immich + - ./vscode:/workspaces/immich/.vscode + - cli_node_modules:/workspaces/immich/cli/node_modules + - e2e_node_modules:/workspaces/immich/e2e/node_modules + - open_api_node_modules:/workspaces/immich/open-api/typescript-sdk/node_modules + - server_node_modules:/workspaces/immich/server/node_modules + - web_node_modules:/workspaces/immich/web/node_modules + - ${UPLOAD_LOCATION}:/workspaces/immich/server/upload + +volumes: + cli_node_modules: + e2e_node_modules: + open_api_node_modules: + server_node_modules: + web_node_modules: + immich: + upload-volume: + db-volume: diff --git a/.devcontainer/mobile/postCreate.sh b/.devcontainer/mobile/postCreate.sh new file mode 100755 index 0000000000..2c479da68b --- /dev/null +++ b/.devcontainer/mobile/postCreate.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# Enable multiarch for arm64 if necessary +if [ "$(dpkg --print-architecture)" = "arm64" ]; then + sudo dpkg --add-architecture amd64 && + sudo apt-get update && + sudo apt-get install -y --no-install-recommends \ + qemu-user-static \ + libc6:amd64 \ + libstdc++6:amd64 \ + libgcc1:amd64 +fi + +dart --disable-analytics + +export IMMICH_PORT="${DEV_SERVER_PORT:-2283}" +export DEV_PORT="${DEV_PORT:-3000}" + +sudo chown node -R /workspaces/immich/.vscode \ + /workspaces/immich/cli/node_modules \ + /workspaces/immich/e2e/node_modules \ + /workspaces/immich/open-api/typescript-sdk/node_modules \ + /workspaces/immich/server/node_modules \ + /workspaces/immich/web/node_modules \ + /workspaces/immich/server/upload + +echo "Installing dependencies (server)" +npm --prefix /workspaces/immich/server install + +echo "Installing dependencies (web)" +npm --prefix /workspaces/immich/open-api/typescript-sdk install +npm --prefix /workspaces/immich/open-api/typescript-sdk run build +npm --prefix /workspaces/immich/web install diff --git a/.devcontainer/scripts/initializeCommand.sh b/.devcontainer/scripts/initializeCommand.sh deleted file mode 100644 index 9d9d196696..0000000000 --- a/.devcontainer/scripts/initializeCommand.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -# If .env file does not exist, create it by copying example.env from the docker folder -if [ ! -f ".devcontainer/.env" ]; then - cp docker/example.env .devcontainer/.env -fi diff --git a/.devcontainer/scripts/onCreateCommand.sh b/.devcontainer/scripts/onCreateCommand.sh deleted file mode 100644 index 2f898ec32e..0000000000 --- a/.devcontainer/scripts/onCreateCommand.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# Enable multiarch for arm64 if necessary -if [ "$(dpkg --print-architecture)" = "arm64" ]; then - sudo dpkg --add-architecture amd64 && \ - sudo apt-get update && \ - sudo apt-get install -y --no-install-recommends \ - qemu-user-static \ - libc6:amd64 \ - libstdc++6:amd64 \ - libgcc1:amd64 -fi - -# Install DCM -wget -qO- https://dcm.dev/pgp-key.public | sudo gpg --dearmor -o /usr/share/keyrings/dcm.gpg -sudo echo 'deb [signed-by=/usr/share/keyrings/dcm.gpg arch=amd64] https://dcm.dev/debian stable main' | sudo tee /etc/apt/sources.list.d/dart_stable.list - -sudo apt-get update -sudo apt-get install dcm - -dart --disable-analytics - -# Install immich -cd /immich || exit -make install-all diff --git a/.devcontainer/server/.env b/.devcontainer/server/.env new file mode 100644 index 0000000000..2d371d8cd9 --- /dev/null +++ b/.devcontainer/server/.env @@ -0,0 +1,14 @@ +# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables + +# The location where your uploaded files are stored +UPLOAD_LOCATION=vol-upload + +# The location where your db files are stored +DB_DATA_LOCATION=vol-database + +# Connection secret for postgres. You should change it to a random password +DB_PASSWORD=postgres + +# The values below this line do not need to be changed +DB_USERNAME=postgres +DB_DATABASE_NAME=immich diff --git a/.devcontainer/server/Dockerfile b/.devcontainer/server/Dockerfile new file mode 100644 index 0000000000..3a93862e6c --- /dev/null +++ b/.devcontainer/server/Dockerfile @@ -0,0 +1,16 @@ +ARG BASEIMAGE=ghcr.io/immich-app/base-server-dev:202503182202@sha256:45ae044b64a7b518f8d94fa4de718090c1c7689d516ac2ac0976a5331eaeb396 +FROM ${BASEIMAGE} AS dev + +RUN apt-get install inetutils-ping sudo -y +RUN usermod -aG sudo node +RUN echo "node ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers +RUN mkdir -p /workspaces/immich +RUN chown node -R /workspaces + +RUN mkdir /immich-devcontainer && chown node -R /immich-devcontainer +COPY --chmod=777 ./.devcontainer/server/common.sh /immich-devcontainer/common.sh +COPY --chmod=777 ./.devcontainer/server/postCreate.sh /immich-devcontainer/postCreate.sh +COPY --chmod=777 ./.devcontainer/server/startNestApiServer.sh /immich-devcontainer/startNestApiServer.sh +COPY --chmod=777 ./.devcontainer/server/startViteWebServer.sh /immich-devcontainer/startViteWebServer.sh + + diff --git a/.devcontainer/server/common.sh b/.devcontainer/server/common.sh new file mode 100755 index 0000000000..6f3ef9bedc --- /dev/null +++ b/.devcontainer/server/common.sh @@ -0,0 +1,23 @@ +#!/bin/bash +export IMMICH_PORT="${DEV_SERVER_PORT:-2283}" +export DEV_PORT="${DEV_PORT:-3000}" + +# search for immich directory inside workspace. +# /workspaces/immich is the bind mount, but other directories can be mounted if runing +# Devcontainer: Clone [repository|pull request] in container volumne +WORKSPACES_DIR="/workspaces" +IMMICH_DIR="$WORKSPACES_DIR/immich" + +# Find directories excluding /workspaces/immich +mapfile -t other_dirs < <(find "$WORKSPACES_DIR" -mindepth 1 -maxdepth 1 -type d ! -path "$IMMICH_DIR" ! -name ".*") + +if [ ${#other_dirs[@]} -gt 1 ]; then + echo "Error: More than one directory found in $WORKSPACES_DIR other than $IMMICH_DIR." + exit 1 +elif [ ${#other_dirs[@]} -eq 1 ]; then + export IMMICH_WORKSPACE="${other_dirs[0]}" +else + export IMMICH_WORKSPACE="$IMMICH_DIR" +fi + +echo "Found immich workspace in $IMMICH_WORKSPACE" diff --git a/.devcontainer/server/docker-compose.yml b/.devcontainer/server/docker-compose.yml new file mode 100644 index 0000000000..832afb8aad --- /dev/null +++ b/.devcontainer/server/docker-compose.yml @@ -0,0 +1,64 @@ +services: + immich-devcontainer-server: + build: + dockerfile: ./.devcontainer/server/Dockerfile + context: ../.. + hostname: immich-devcontainer-server + extra_hosts: + - 'host.docker.internal:host-gateway' + environment: + - IMMICH_SERVER_URL=http://127.0.0.1:2283/ + - REDIS_PORT=6400 + - REDIS_HOSTNAME=immich-devcontainer-redis + - DB_PORT=5500 + - DB_HOSTNAME=immich-devcontainer-database + volumes: + # bind mount host to /workspaces/immich + - ../..:/workspaces/immich + - ./vscode:/workspaces/immich/.vscode + - cli_node_modules:/workspaces/immich/cli/node_modules + - e2e_node_modules:/workspaces/immich/e2e/node_modules + - open_api_node_modules:/workspaces/immich/open-api/typescript-sdk/node_modules + - server_node_modules:/workspaces/immich/server/node_modules + - web_node_modules:/workspaces/immich/web/node_modules + - ${UPLOAD_LOCATION}:/workspaces/immich/server/upload + + immich-devcontainer-redis: + image: redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8 + command: redis-server --port 6400 + healthcheck: + test: redis-cli ping || exit 1 + + immich-devcontainer-database: + image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52 + env_file: + - .env + environment: + PGPORT: 5500 + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_USER: ${DB_USERNAME} + POSTGRES_DB: ${DB_DATABASE_NAME} + POSTGRES_INITDB_ARGS: '--data-checksums' + volumes: + - ${DB_DATA_LOCATION}:/var/lib/postgresql/data + ports: + - 5432:5432 + healthcheck: + test: >- + pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1 + interval: 5m + start_period: 5m + command: >- + postgres -c shared_preload_libraries=vectors.so -c 'search_path="$$user", public, vectors' -c logging_collector=on -c max_wal_size=2GB -c shared_buffers=512MB -c wal_compression=on + +volumes: + cli_node_modules: + e2e_node_modules: + open_api_node_modules: + server_node_modules: + web_node_modules: + immich: + # UPLOAD_LOCATION must be set to a absolute path or vol-upload + vol-upload: + # DB_DATA_LOCATION must be set to a absolute path or vol-database + vol-database: diff --git a/.devcontainer/server/postCreate.sh b/.devcontainer/server/postCreate.sh new file mode 100755 index 0000000000..8c629a6337 --- /dev/null +++ b/.devcontainer/server/postCreate.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# shellcheck source=common.sh +source /immich-devcontainer/common.sh + +sudo find "${IMMICH_WORKSPACE}/server/upload" -not -path "${IMMICH_WORKSPACE}/server/upload/postgres/*" -not -path "${IMMICH_WORKSPACE}/server/upload/postgres" -exec chown node {} + + +sudo chown node -R "${IMMICH_WORKSPACE}/.vscode" \ + "${IMMICH_WORKSPACE}/cli/node_modules" \ + "${IMMICH_WORKSPACE}/e2e/node_modules" \ + "${IMMICH_WORKSPACE}/open-api/typescript-sdk/node_modules" \ + "${IMMICH_WORKSPACE}/server/node_modules" \ + "${IMMICH_WORKSPACE}/server/dist" \ + "${IMMICH_WORKSPACE}/web/node_modules" \ + "${IMMICH_WORKSPACE}/web/dist" + +echo "Installing dependencies (server)" +echo npm --prefix "${IMMICH_WORKSPACE}/server" install +npm --prefix "${IMMICH_WORKSPACE}/server" install + +echo "Installing dependencies (web)" +echo npm --prefix "${IMMICH_WORKSPACE}/open-api/typescript-sdk" install +npm --prefix "${IMMICH_WORKSPACE}/open-api/typescript-sdk" install +echo npm --prefix "${IMMICH_WORKSPACE}/open-api/typescript-sdk" run build +npm --prefix "${IMMICH_WORKSPACE}/open-api/typescript-sdk" run build +echo npm --prefix "${IMMICH_WORKSPACE}/web" install +npm --prefix "${IMMICH_WORKSPACE}/web" install diff --git a/.devcontainer/server/startNestApiServer.sh b/.devcontainer/server/startNestApiServer.sh new file mode 100755 index 0000000000..111239d6f5 --- /dev/null +++ b/.devcontainer/server/startNestApiServer.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# shellcheck source=common.sh +source /immich-devcontainer/common.sh + +echo "Starting Nest API Server" + +cd "${IMMICH_WORKSPACE}/server" || ( + echo workspace not found + exit 1 +) + +while true; do + node ./node_modules/.bin/nest start --debug "0.0.0.0:9230" --watch + echo " Nest API Server crashed with exit code $?. Respawning in 3s ..." + sleep 3 +done diff --git a/.devcontainer/server/startViteWebServer.sh b/.devcontainer/server/startViteWebServer.sh new file mode 100755 index 0000000000..4dae803fea --- /dev/null +++ b/.devcontainer/server/startViteWebServer.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# shellcheck source=common.sh +source /immich-devcontainer/common.sh + +until curl --output /dev/null --silent --head --fail "http://127.0.0.1:${IMMICH_PORT}/api/server/config"; do + echo 'waiting for api server...' + sleep 1 +done + +echo "Starting web" +cd "${IMMICH_WORKSPACE}/web" || ( + echo workspace not found + exit 1 +) + +while true; do + node ./node_modules/.bin/vite dev --host 0.0.0.0 --port "${DEV_PORT}" + echo "Web crashed with exit code $?. Respawning in 3s ..." + sleep 3 +done diff --git a/.devcontainer/server/vscode/launch.json b/.devcontainer/server/vscode/launch.json new file mode 100644 index 0000000000..4ed13b0524 --- /dev/null +++ b/.devcontainer/server/vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "attach", + "restart": true, + "port": 9231, + "name": "Immich API Server", + "remoteRoot": "/usr/src/app", + "localRoot": "${workspaceFolder}/server" + }, + { + "type": "node", + "request": "attach", + "restart": true, + "port": 9230, + "name": "Immich Workers", + "remoteRoot": "/usr/src/app", + "localRoot": "${workspaceFolder}/server" + + } + ] +} diff --git a/.devcontainer/server/vscode/settings.json b/.devcontainer/server/vscode/settings.json new file mode 100644 index 0000000000..396755a634 --- /dev/null +++ b/.devcontainer/server/vscode/settings.json @@ -0,0 +1,63 @@ +{ + "[css]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "[dart]": { + "editor.defaultFormatter": "Dart-Code.dart-code", + "editor.formatOnSave": true, + "editor.selectionHighlight": false, + "editor.suggest.snippetsPreventQuickSuggestions": false, + "editor.suggestSelection": "first", + "editor.tabCompletion": "onlySnippets", + "editor.wordBasedSuggestions": "off" + }, + "[javascript]": { + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.removeUnusedImports": "explicit" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "[svelte]": { + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.removeUnusedImports": "explicit" + }, + "editor.defaultFormatter": "svelte.svelte-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "[typescript]": { + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.removeUnusedImports": "explicit" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "cSpell.words": ["immich"], + "editor.formatOnSave": true, + "eslint.validate": ["javascript", "svelte"], + "explorer.fileNesting.enabled": true, + "explorer.fileNesting.patterns": { + "*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart", + "*.ts": "${capture}.spec.ts,${capture}.mock.ts" + }, + "svelte.enable-ts-plugin": true, + "typescript.preferences.importModuleSpecifier": "non-relative" +} diff --git a/.devcontainer/server/vscode/tasks.json b/.devcontainer/server/vscode/tasks.json new file mode 100644 index 0000000000..f07f373ce2 --- /dev/null +++ b/.devcontainer/server/vscode/tasks.json @@ -0,0 +1,47 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Immich API Server (Nest)", + "type": "shell", + "command": "/immich-devcontainer/startNestApiServer.sh", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": true + }, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "Immich Web Server (Vite)", + "type": "shell", + "command": "/immich-devcontainer/startViteWebServer.sh", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": true + }, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "Immich Server and Web", + "dependsOn": ["Immich Web Server (Vite)", "Immich API Server (Nest)"], + "runOptions": { + "runOn": "folderOpen" + }, + "problemMatcher": [] + } + ] +} diff --git a/docs/docs/developer/devcontainers.md b/docs/docs/developer/devcontainers.md new file mode 100644 index 0000000000..48617856de --- /dev/null +++ b/docs/docs/developer/devcontainers.md @@ -0,0 +1,71 @@ +--- +sidebar_position: 3 +--- + +## Dev Containers + +### Getting started with Dev Containers + +The Dev Container is a fully featured dev environment. It is a portable way, using docker containers, to set up a dev environment. With a single click, you can get started with a Immich environment, on Mac, Linux or Windows or the cloud, like GitHub codespaces. + +[![Open in VSCode Containers](https://img.shields.io/static/v1?label=VSCode%20DevContainer&message=Immich&color=blue)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/immich-app/immich/) + +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/immich-app/immich/) + +[More info on dev containers here](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers) + +### Details + +The Immich dev container runs the web and server in one container, and redis and ML each in their own container. + +By default, if you don't customize any ENV VARs, when you start the Immich dev container, it will be configured to use volumes for the upload and database locations on disk. These volumes are persistent, and they last between container rebuilds and restarts. + +In non-cloud environments, you can optionally use host filesystem paths instead of volumes - this will allow you to store the upload directory and database directory on the host filesystem, rather than a volume. + +### Launching Dev Container from a cloned repo + +1. Clone the project repo. +2. Open VS Code +3. Press ctrl/command-p type ">Dev Containers: Rebuild and Reopen in Container" +4. Select "Immich - Backend and Frontend" +5. Wait a while - after the builds are done, the server and web processes will be started as tasks, and the browser will be opened (once) to the front page. + +## Configuring Database and Upload paths to the host + +ENV VARs can use to control the location of the upload and the database paths. + +### UPLOAD_LOCATION + +The default for `UPLOAD_LOCATION` is `vol-upload` which is a volume mount. + +The only supported value when using volumes is `vol-upload`. This is because it is hard-coded as a named volume in the `.devcontainer/server/docker-compose.yaml` file. + +To use a bind mount instead, simply set `UPLOAD_LOCATION` to an **absolute** path on the host file system instead. This must be added to the `.bash_profile` if your using bash, or equivalent for other shells. + +```bash +export UPLOAD_LOCATION=/data/my/upload/path +``` + +### DB_DATA_LOCATION + +The default for `DB_DATA_LOCATION` is `vol-database` which is a volume mount. + +The only supported value when using volumes is `vol-database` since it hard-coded as a named volume in the `.devcontainer/server/docker-compose.yaml` file. + +To use a bind mount instead, simply set `DB_DATA_LOCATION` to an **absolute** path on the host file system instead. This must be added to the `.bash_profile` if your using bash, or equivalent for other shells. + +```bash +export DB_DATA_LOCATION=/data/my/upload/path +``` + +### Other Variables + +Its unlikely, but in case you modified the username/password of the database, you can control these values using the following ENV VARs: + +```bash +export DB_PASSWORD=postgres +export DB_USERNAME=postgres +export DB_DATABASE_NAME=immich +``` + +This must be added to the `.bash_profile` if your using bash, or equivalent for other shells.