mirror of
https://github.com/immich-app/immich.git
synced 2025-01-21 00:52:43 -05:00
wip - test
This commit is contained in:
parent
4fcb757cf5
commit
3cb6ae3560
17 changed files with 271 additions and 32 deletions
2
cli/package-lock.json
generated
2
cli/package-lock.json
generated
|
@ -54,7 +54,7 @@
|
|||
"@oazapfts/runtime": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
|
|
21
docker/Caddyfile
Normal file
21
docker/Caddyfile
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
|
||||
:443 {
|
||||
tls internal {
|
||||
on_demand
|
||||
}
|
||||
reverse_proxy immich-web:3000
|
||||
log {
|
||||
output file /logs/caddy.log
|
||||
}
|
||||
}
|
||||
|
||||
:444 {
|
||||
tls internal {
|
||||
on_demand
|
||||
}
|
||||
reverse_proxy immich-server:3001
|
||||
log {
|
||||
output file /logs/caddy.log
|
||||
}
|
||||
}
|
|
@ -5,6 +5,24 @@
|
|||
name: immich-dev
|
||||
|
||||
services:
|
||||
nginx:
|
||||
container_name: nginx_web
|
||||
image: nginx
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ../web/build:/usr/share/immich-web:ro
|
||||
ports:
|
||||
- 5000:80
|
||||
caddy:
|
||||
container_name: immich_caddy
|
||||
image: caddy
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- caddy_data:/data
|
||||
ports:
|
||||
- 5001:443
|
||||
- 5002:444
|
||||
- 2019:2019
|
||||
immich-server:
|
||||
container_name: immich_server
|
||||
command: ['/usr/src/app/bin/immich-dev']
|
||||
|
@ -19,6 +37,7 @@ services:
|
|||
restart: always
|
||||
volumes:
|
||||
- ../server:/usr/src/app
|
||||
- ../server/node_modules:/usr/src/node_modules
|
||||
- ../open-api:/usr/src/open-api
|
||||
- ${UPLOAD_LOCATION}/photos:/usr/src/app/upload
|
||||
- ${UPLOAD_LOCATION}/photos/upload:/usr/src/app/upload/upload
|
||||
|
@ -107,7 +126,22 @@ services:
|
|||
interval: 5m
|
||||
start_interval: 30s
|
||||
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"]
|
||||
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',
|
||||
]
|
||||
|
||||
# set IMMICH_METRICS=true in .env to enable metrics
|
||||
# immich-prometheus:
|
||||
|
@ -131,6 +165,7 @@ services:
|
|||
# - grafana-data:/var/lib/grafana
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
model-cache:
|
||||
prometheus-data:
|
||||
grafana-data:
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
name: immich-prod
|
||||
|
||||
services:
|
||||
nginx:
|
||||
container_name: nginx_web
|
||||
image: nginx
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ../web/build:/usr/share/immich-web:ro
|
||||
ports:
|
||||
- 5000:80
|
||||
immich-server:
|
||||
container_name: immich_server
|
||||
image: immich-server:latest
|
||||
|
@ -15,6 +23,8 @@ services:
|
|||
- /etc/localtime:/etc/localtime:ro
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- IMMICH_ENV=production
|
||||
ports:
|
||||
- 2283:3001
|
||||
depends_on:
|
||||
|
@ -65,7 +75,22 @@ services:
|
|||
interval: 5m
|
||||
start_interval: 30s
|
||||
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"]
|
||||
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',
|
||||
]
|
||||
restart: always
|
||||
|
||||
# set IMMICH_METRICS=true in .env to enable metrics
|
||||
|
|
40
docker/nginx.conf
Normal file
40
docker/nginx.conf
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;\
|
||||
server {
|
||||
listen 80;
|
||||
location / {
|
||||
root /usr/share/immich-web;
|
||||
index index.html;
|
||||
if (!-e $request_filename) {
|
||||
rewrite ^(.*)$ /index.html break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
23
docker/test.yml
Normal file
23
docker/test.yml
Normal file
|
@ -0,0 +1,23 @@
|
|||
# See:
|
||||
# - https://immich.app/docs/developer/setup
|
||||
# - https://immich.app/docs/developer/troubleshooting
|
||||
|
||||
name: immich-dev
|
||||
|
||||
services:
|
||||
|
||||
caddy:
|
||||
container_name: immich_caddy
|
||||
image: caddy
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- caddy_data:/data
|
||||
ports:
|
||||
- 5001:443
|
||||
- 2019:2019
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
model-cache:
|
||||
prometheus-data:
|
||||
grafana-data:
|
2
e2e/package-lock.json
generated
2
e2e/package-lock.json
generated
|
@ -88,7 +88,7 @@
|
|||
"@oazapfts/runtime": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -5,7 +5,7 @@ import { CookieResponse, ImmichCookie } from 'src/dtos/auth.dto';
|
|||
export const respondWithCookie = <T>(res: Response, body: T, { isSecure, values }: CookieResponse) => {
|
||||
const defaults: CookieOptions = {
|
||||
path: '/',
|
||||
sameSite: 'lax',
|
||||
sameSite: 'none',
|
||||
httpOnly: true,
|
||||
secure: isSecure,
|
||||
maxAge: Duration.fromObject({ days: 400 }).toMillis(),
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import { CorsOptionsCallback, CustomOrigin } from '@nestjs/common/interfaces/external/cors-options.interface';
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { NestExpressApplication } from '@nestjs/platform-express';
|
||||
import { json } from 'body-parser';
|
||||
import cookieParser from 'cookie-parser';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import { existsSync } from 'node:fs';
|
||||
import sirv from 'sirv';
|
||||
import { ApiModule } from 'src/app.module';
|
||||
import { envName, excludePaths, isDev, serverVersion, WEB_ROOT } from 'src/constants';
|
||||
import { WEB_ROOT, envName, excludePaths, isDev, serverVersion } from 'src/constants';
|
||||
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
||||
import { WebSocketAdapter } from 'src/middleware/websocket.adapter';
|
||||
import { ApiService } from 'src/services/api.service';
|
||||
|
@ -22,8 +24,15 @@ async function bootstrap() {
|
|||
|
||||
const port = Number(process.env.IMMICH_PORT) || 3001;
|
||||
const app = await NestFactory.create<NestExpressApplication>(ApiModule, { bufferLogs: true });
|
||||
// app.use((req: Request, res: Response, next: NextFunction) => {
|
||||
// console.log(req.url);
|
||||
// console.log(req.get('origin'));
|
||||
// console.log(req.get('host'));
|
||||
// debugger;
|
||||
// next();
|
||||
// });
|
||||
const logger = await app.resolve<ILoggerRepository>(ILoggerRepository);
|
||||
|
||||
//i
|
||||
logger.setAppName('Api');
|
||||
logger.setContext('Bootstrap');
|
||||
app.useLogger(logger);
|
||||
|
@ -31,8 +40,32 @@ async function bootstrap() {
|
|||
app.set('etag', 'strong');
|
||||
app.use(cookieParser());
|
||||
app.use(json({ limit: '10mb' }));
|
||||
debugger; // oddkjkjjh
|
||||
const origins: CustomOrigin = (_, cb) => {
|
||||
console.log('hi');
|
||||
debugger;
|
||||
cb(null, [
|
||||
'http://192.168.4.248:2283',
|
||||
'http://docker-dev:2283',
|
||||
'https://docker-dev:5002',
|
||||
'https://192.168.4.248:5001',
|
||||
]);
|
||||
};
|
||||
|
||||
if (isDev()) {
|
||||
app.enableCors();
|
||||
debugger;
|
||||
app.enableCors((req, cb) => {
|
||||
if (req.get('origin')) {
|
||||
cb(null, {
|
||||
credentials: true,
|
||||
origin: origins,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
|
||||
allowedHeaders: ['content-type', '*'],
|
||||
});
|
||||
} else {
|
||||
cb(null, { origin: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
app.useWebSocketAdapter(new WebSocketAdapter(app));
|
||||
useSwagger(app);
|
||||
|
|
32
web/nginx.conf
Normal file
32
web/nginx.conf
Normal file
|
@ -0,0 +1,32 @@
|
|||
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
2
web/package-lock.json
generated
2
web/package-lock.json
generated
|
@ -74,7 +74,7 @@
|
|||
"@oazapfts/runtime": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -15,7 +15,8 @@ export const loadUser = async () => {
|
|||
try {
|
||||
let user = get(user$);
|
||||
let preferences = get(preferences$);
|
||||
if ((!user || !preferences) && hasAuthCookie()) {
|
||||
debugger;
|
||||
if (!user || !preferences) {
|
||||
[user, preferences] = await Promise.all([getMyUser(), getMyPreferences()]);
|
||||
user$.set(user);
|
||||
preferences$.set(preferences);
|
||||
|
|
|
@ -5,20 +5,23 @@ const wait = (ms: number) => new Promise((_, reject) => setTimeout(reject, ms));
|
|||
|
||||
const tryServers = async (fetchFn: typeof fetch) => {
|
||||
const server_urls_env = env.PUBLIC_SERVER_URLS;
|
||||
if (server_urls_env) {
|
||||
const servers = server_urls_env.split(',');
|
||||
// servers are in priority order, try in parallel, use first success
|
||||
const fetchers = servers.map((url) => ({ url, fetcher: fetchFn(`${url}/server-info/config`) }));
|
||||
for (const { url, fetcher } of fetchers) {
|
||||
try {
|
||||
const response = (await Promise.race([fetcher, wait(1000)])) as Response;
|
||||
if (response?.ok) {
|
||||
defaults.basePath = url;
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
// ignore, handled upstream
|
||||
|
||||
let servers = server_urls_env.split(',');
|
||||
servers = ['https://docker-dev:5002/api'];
|
||||
// servers = [];
|
||||
// servers are in priority order, try in parallel, use first success
|
||||
const fetchers = servers.map((url) => ({ url, fetcher: fetchFn(`${url}/server-info/config`) }));
|
||||
for (const { url, fetcher } of fetchers) {
|
||||
try {
|
||||
const response = (await Promise.race([fetcher, wait(1000)])) as Response;
|
||||
if (response?.ok) {
|
||||
debugger;
|
||||
defaults.baseUrl = url;
|
||||
defaults.credentials = 'include';
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
// ignore, handled upstream
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,16 @@ import type { LayoutLoad } from './$types';
|
|||
|
||||
export const ssr = false;
|
||||
export const csr = true;
|
||||
export const prerender = true;
|
||||
|
||||
export const load = (async ({ fetch }) => {
|
||||
for (const { code, loader } of langs) {
|
||||
register(code, loader);
|
||||
}
|
||||
|
||||
const preferenceLang = get(lang);
|
||||
|
||||
await init({ fallbackLocale: preferenceLang === 'dev' ? 'dev' : defaultLang.code, initialLocale: preferenceLang });
|
||||
let hasError = false;
|
||||
try {
|
||||
await initSDK(fetch);
|
||||
|
@ -17,14 +25,6 @@ export const load = (async ({ fetch }) => {
|
|||
hasError = true;
|
||||
}
|
||||
|
||||
for (const { code, loader } of langs) {
|
||||
register(code, loader);
|
||||
}
|
||||
|
||||
const preferenceLang = get(lang);
|
||||
|
||||
await init({ fallbackLocale: preferenceLang === 'dev' ? 'dev' : defaultLang.code, initialLocale: preferenceLang });
|
||||
|
||||
return {
|
||||
hasError,
|
||||
meta: {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { AppRoute } from '$lib/constants';
|
||||
import { initSDK } from '$lib/utils/server';
|
||||
import { getServerConfig } from '@immich/sdk';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
@ -10,6 +11,14 @@ export const ssr = false;
|
|||
export const csr = true;
|
||||
|
||||
export const load = (async () => {
|
||||
let hasError = false;
|
||||
try {
|
||||
await initSDK(fetch);
|
||||
} catch {
|
||||
// error pages use page layouts, so can't throw error - catch it and display error message in layout.
|
||||
hasError = true;
|
||||
}
|
||||
debugger;
|
||||
const authenticated = await loadUser();
|
||||
if (authenticated) {
|
||||
redirect(302, AppRoute.PHOTOS);
|
||||
|
@ -24,6 +33,7 @@ export const load = (async () => {
|
|||
const $t = get(t);
|
||||
|
||||
return {
|
||||
hasError,
|
||||
meta: {
|
||||
title: $t('welcome') + ' 🎉',
|
||||
description: $t('immich_web_interface'),
|
||||
|
|
|
@ -5,8 +5,18 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|||
const config = {
|
||||
preprocess: vitePreprocess(),
|
||||
kit: {
|
||||
prerender: {
|
||||
handleHttpError: ({ path, referrer, message }) => {
|
||||
if (path === '/custom.css') {
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise fail the build
|
||||
throw new Error(message);
|
||||
},
|
||||
},
|
||||
adapter: adapter({
|
||||
fallback: 'index.html',
|
||||
// fallback: 'index.html',
|
||||
precompress: true,
|
||||
}),
|
||||
alias: {
|
||||
|
|
|
@ -13,6 +13,9 @@ const upstream = {
|
|||
};
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
minify: false,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'xmlhttprequest-ssl': './node_modules/engine.io-client/lib/xmlhttprequest.js',
|
||||
|
@ -27,6 +30,9 @@ export default defineConfig({
|
|||
'/.well-known/immich': upstream,
|
||||
'/custom.css': upstream,
|
||||
},
|
||||
cors: {
|
||||
origin: false,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
sveltekit(),
|
||||
|
|
Loading…
Add table
Reference in a new issue