diff --git a/.github/workflows/publish-images.yml b/.github/workflows/publish-images.yml
index 63b421e6..187bb742 100644
--- a/.github/workflows/publish-images.yml
+++ b/.github/workflows/publish-images.yml
@@ -5,8 +5,7 @@ on:
inputs:
tags:
description: "Tags for the image"
- required: true
- default: "debug"
+ required: false
images:
description: "Images to build and push"
required: true
diff --git a/README.md b/README.md
index 799a7f3d..a379d2ee 100644
--- a/README.md
+++ b/README.md
@@ -196,29 +196,29 @@ The server is configured via a config file. Here is an example config file:
```json5
{
- "connection": {
- "port": 5101,
+ connection: {
+ port: 5101,
// for the example retrom-db container below
- "db_url": "postgres://minecraft_steve:super_secret_password@retrom-db/retrom"
+ db_url: "postgres://minecraft_steve:super_secret_password@retrom-db/retrom",
// or, bring your own database:
// "db_url": "postgres://{db_user}:{db_password}@{db_host}/{db_name}"
},
- "content_directories": [
+ content_directories: [
{
- "path": "path/to/my/library/",
- "storage_type": "MultiFileGame"
+ path: "path/to/my/library/",
+ storage_type: "MultiFileGame",
},
{
- "path": "path/to/my/library/with/single_file_games/",
- "storage_type": "SingleFileGame"
- }
+ path: "path/to/my/library/with/single_file_games/",
+ storage_type: "SingleFileGame",
+ },
],
- "igdb": {
- "client_secret": "super_secret_client_secret!!!1",
- "client_id": "my_IGDB_ID_1234"
- }
+ igdb: {
+ client_secret: "super_secret_client_secret!!!1",
+ client_id: "my_IGDB_ID_1234",
+ },
}
```
@@ -239,24 +239,24 @@ Here is the example config file:
```json5
{
- "connection": {
- "port": 5101,
- "db_url": "postgres://minecraft_steve:super_secret_password@retrom-db/retrom"
+ connection: {
+ port: 5101,
+ db_url: "postgres://minecraft_steve:super_secret_password@retrom-db/retrom",
},
- "content_directories": [
+ content_directories: [
{
- "path": "/library1", // this path is **inside the container**
- "storage_type": "MultiFileGame"
+ path: "/library1", // this path is **inside the container**
+ storage_type: "MultiFileGame",
},
{
- "path": "/library2", // this path is **inside the container**
- "storage_type": "SingleFileGame"
- }
+ path: "/library2", // this path is **inside the container**
+ storage_type: "SingleFileGame",
+ },
],
- "igdb": {
- "client_secret": "super_secret_client_secret!!!1",
- "client_id": "my_IGDB_ID_1234"
- }
+ igdb: {
+ client_secret: "super_secret_client_secret!!!1",
+ client_id: "my_IGDB_ID_1234",
+ },
}
```
@@ -268,6 +268,7 @@ services:
image: ghcr.io/jmberesford/retrom-service:latest
ports:
- 5101:5101
+ - 3000:3000 # to access the web client
volumes:
- /home/minecraft_steve/config_dir:/config/ # directory containing your config file
- /home/minecraft_steve/library1:/library1 # directory containing your first library
@@ -289,11 +290,12 @@ services:
POSTGRES_USER: minecraft_steve # db user, used to connect to the db, should match the db_user in your config file
POSTGRES_PASSWORD: super_secret_password # db password for above user, should match the db_password in your config file
POSTGRES_DB: retrom # db name, should match the db_name in your config file
-
```
You can then run `docker-compose up` in the directory containing your `docker-compose.yml` file to start the service.
+The web client will be accessible at port 3000, and the service itself on port 5101 -- which can be accessed by any desktop clients.
+
### Client
#### Desktop Client
@@ -319,21 +321,5 @@ The following may help you differentiate between the different versions:
#### Web Client
-> [!NOTE]
-> There are plans to bundle the web client along with the service in a single container in the future,
-> for ease of use.
-
-The web client is currently only available as a Docker container. You can run it with the following
-`docker-compose.yml` file, as an example:
-
-```yaml
-retrom-web:
- image: ghcr.io/jmberesford/retrom-web:latest
- container_name: retrom-web
- hostname: retrom-web
- ports:
- - 3000:3000
-```
-
-Then, you can run `docker-compose up` in the directory containing your `docker-compose.yml` file to start the service.
-You can then reach the web client at `http://localhost:3000` in your browser, if running locally.
+> [!WARNING]
+> The web client image has been deprecated. Use the web client bundled with the service image instead.
diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.yml
similarity index 65%
rename from docker/docker-compose.dev.yml
rename to docker/docker-compose.yml
index 1f147772..f0f720c1 100644
--- a/docker/docker-compose.dev.yml
+++ b/docker/docker-compose.yml
@@ -30,25 +30,11 @@ services:
hostname: retrom
env_file: ./.env
ports:
- - 5101:${RETROM_PORT:-5101}
+ - 5101:5101
+ - 3000:3000
volumes:
- ${CONTENT_DIR1:-./mock_content/}/:/lib1
- ${CONTENT_DIR2:-./mock_content_single}:/lib2
- - ${CONFIG_DIR:-./config-dev/}:/config
+ - ${CONFIG_DIR:-./config_dev/}:/config
depends_on:
- retrom-db
-
- retrom-web:
- build:
- context: ../
- dockerfile: docker/web.Dockerfile
- container_name: retrom-web
- hostname: retrom-web
- env_file: ./.env
- ports:
- - 3000:${RETROM_WEB_PORT:-3000}
- environment:
- VITE_RETROM_WEB_PORT: ${RETROM_WEB_PORT:-3000}
- VITE_RETROM_HOST: ${RETROM_HOST:-retrom:5101}
- depends_on:
- - retrom
diff --git a/docker/service.Dockerfile b/docker/service.Dockerfile
index 72477204..a936c8a6 100644
--- a/docker/service.Dockerfile
+++ b/docker/service.Dockerfile
@@ -1,26 +1,67 @@
-FROM rust:slim-bookworm as builder
+FROM node:20-bookworm-slim AS common
+COPY . ./app
+
+### WEB CLIENT
+FROM node:20-bookworm-slim AS base
+ENV PNPM_HOME="/pnpm"
+ENV PATH="$PNPM_HOME:$PATH"
+RUN corepack enable
+
+FROM base AS web-builder
+RUN apt-get update && apt-get install protobuf-compiler ca-certificates -y
+
+COPY --from=common /app /app
+WORKDIR /app
+
+RUN pnpm install --frozen-lockfile
+RUN pnpm exec buf generate
+RUN pnpm --filter=web build
+RUN pnpm deploy --filter=web /web
+RUN mv /app/packages/client/web/dist /web/dist
+
+### SERVICE BINARY
+FROM rust:slim-bookworm AS service-builder
+
+COPY --from=common /app /usr/src/retrom
WORKDIR /usr/src/retrom
-COPY . .
RUN apt-get update && apt-get install protobuf-compiler openssl pkg-config libssl-dev libpq-dev -y
RUN cargo install --path ./packages/service
-FROM debian:bookworm-slim
-RUN apt-get update && apt-get install openssl libssl-dev libpq-dev ca-certificates -y && rm -rf /var/lib/apt/lists/*
+FROM base AS runner
+ENV UID=1505
+ENV GID=1505
+ENV UMASK=000
+ENV USER=retrom
-ENV UID=1001
-ENV GID=1001
+RUN addgroup --gid $GID ${USER}
+RUN adduser --gid $GID --uid $UID ${USER}
+
+RUN apt-get update && apt-get install openssl libssl-dev libpq-dev ca-certificates -y
+
+### Service env
ENV RUST_LOG=info
+ENV RETROM_CONFIG=/config/config.json
+EXPOSE 5101
+
+### Web env
+ENV NODE_ENV=production
+ENV RETROM_LOCAL_SERVICE_HOST=http://localhost:5101
+EXPOSE 3000
-RUN addgroup --system --gid $GID retrom
-RUN adduser --system --uid $UID retrom
+COPY --from=service-builder /usr/local/cargo/bin/retrom-service /app/retrom-service
+COPY docker/start.sh /app/start.sh
+RUN chmod +x /app/start.sh
-COPY --from=builder /usr/local/cargo/bin/retrom-service /app/retrom-service
+COPY --from=web-builder /web /app/web
+
+RUN chmod -R 777 /app/web
WORKDIR /app
-USER retrom
-ENV RETROM_CONFIG=/config/config.json
+USER ${USER}
+
+RUN umask ${UMASK}
-CMD ["./retrom-service"]
+CMD ./start.sh
diff --git a/docker/start.sh b/docker/start.sh
new file mode 100644
index 00000000..d064154a
--- /dev/null
+++ b/docker/start.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -e
+
+# Start the web server
+cd /app/web
+pnpm preview &
+
+# Start the API server
+cd /app
+
+./retrom-service &
+
+wait -n
+
+exit $?
diff --git a/docker/web.Dockerfile b/docker/web.Dockerfile
index 32c8fade..883d27a9 100644
--- a/docker/web.Dockerfile
+++ b/docker/web.Dockerfile
@@ -1,48 +1,4 @@
-FROM node:20-alpine AS base
+FROM alpine:3.14
-FROM base AS deps
-RUN apk add --no-cache libc6-compat protobuf-dev
-WORKDIR /app
+CMD echo 'This image has been deprecated. Please use the web-client bundled in retrom-service.' && exit 1
-# top level deps
-COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
-
-# package deps
-RUN mkdir -p packages/client/ && mkdir -p packages/codegen/
-COPY buf*.yaml ./
-COPY packages/codegen/protos/ ./packages/codegen/protos/
-COPY packages/client/package.json ./packages/client/
-COPY packages/client/web/ ./packages/client/web/
-
-RUN corepack enable pnpm && pnpm i
-
-RUN pnpm exec buf generate
-
-FROM base AS builder
-WORKDIR /app
-COPY --from=deps /app/. ./
-
-RUN corepack enable pnpm && pnpm --filter web build
-
-FROM base AS runner
-WORKDIR /app
-
-ENV NODE_ENV=production
-ENV UID=1001
-ENV GID=1001
-ENV PORT=3000
-ENV RETROM_PORT=5101
-ENV RETROM_HOSTNAME=http://localhost
-ENV RETROM_HOST=http://localhost:5101
-
-RUN addgroup --system --gid $GID retrom
-RUN adduser --system --uid $UID retrom
-
-
-COPY --from=builder --chown=retrom:retrom /app/packages/client/web/dist ./dist
-
-USER retrom
-
-EXPOSE $PORT
-
-CMD npx vite preview --host --port $PORT
diff --git a/packages/client/web/package.json b/packages/client/web/package.json
index c66a89ac..e755be73 100644
--- a/packages/client/web/package.json
+++ b/packages/client/web/package.json
@@ -2,6 +2,7 @@
"name": "web",
"private": true,
"type": "module",
+ "packageManager": "pnpm@9.5.0",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
diff --git a/packages/client/web/src/components/menubar/file-menu/index.tsx b/packages/client/web/src/components/menubar/file-menu/index.tsx
index 240e00bf..a4ca30cf 100644
--- a/packages/client/web/src/components/menubar/file-menu/index.tsx
+++ b/packages/client/web/src/components/menubar/file-menu/index.tsx
@@ -5,7 +5,6 @@ import {
MenubarSeparator,
} from "@/components/ui/menubar";
import { ConfigMenuItem } from "./config-menu-item";
-import { DesktopOnly } from "@/lib/env";
import { CloseMenuItem } from "./close-menu-item";
export function FileMenu() {
@@ -18,11 +17,9 @@ export function FileMenu() {
-
-
+
-
-
+
);
diff --git a/packages/client/web/src/components/menubar/index.tsx b/packages/client/web/src/components/menubar/index.tsx
index 38d91713..09f66370 100644
--- a/packages/client/web/src/components/menubar/index.tsx
+++ b/packages/client/web/src/components/menubar/index.tsx
@@ -21,7 +21,9 @@ export function Menubar() {
Retrom
-
+
+
+
diff --git a/packages/client/web/src/components/modals/setup/context.tsx b/packages/client/web/src/components/modals/setup/context.tsx
index b6fa451c..e0f63cb4 100644
--- a/packages/client/web/src/components/modals/setup/context.tsx
+++ b/packages/client/web/src/components/modals/setup/context.tsx
@@ -1,4 +1,3 @@
-import { checkIsDesktop } from "@/lib/env";
import { useNavigate } from "@tanstack/react-router";
import {
createContext,
@@ -33,7 +32,7 @@ export function useSetupModal() {
}
const nextStepTransitions: Record = {
- ServerHost: checkIsDesktop() ? "ClientName" : "Confirm",
+ ServerHost: "ClientName",
ClientName: "Confirm",
Confirm: "ServerHost",
};
@@ -41,7 +40,7 @@ const nextStepTransitions: Record = {
const previousStepTransitions: Record = {
ServerHost: undefined,
ClientName: "ServerHost",
- Confirm: checkIsDesktop() ? "ClientName" : "ServerHost",
+ Confirm: "ClientName",
};
export function SetupModalProvider(props: React.PropsWithChildren) {
diff --git a/packages/client/web/src/components/modals/setup/index.tsx b/packages/client/web/src/components/modals/setup/index.tsx
index bb7359e1..2c4f3bfe 100644
--- a/packages/client/web/src/components/modals/setup/index.tsx
+++ b/packages/client/web/src/components/modals/setup/index.tsx
@@ -2,17 +2,20 @@ import { Dialog, DialogContent } from "@/components/ui/dialog";
import { SetupModalProvider } from "./context";
import { SetupModalSteps } from "./steps";
import { Route as RootRoute } from "@/routes/__root";
+import { DesktopOnly } from "@/lib/env";
export function SetupModal() {
const { setupModal } = RootRoute.useSearch();
return (
-
+
+
+
);
}
diff --git a/packages/client/web/src/providers/retrom-client/index.tsx b/packages/client/web/src/providers/retrom-client/index.tsx
index b08fa36d..d00765f8 100644
--- a/packages/client/web/src/providers/retrom-client/index.tsx
+++ b/packages/client/web/src/providers/retrom-client/index.tsx
@@ -1,6 +1,7 @@
import { PropsWithChildren, createContext, useContext, useMemo } from "react";
import { RetromClient } from "./client";
import { useConfig } from "../config";
+import { checkIsDesktop } from "@/lib/env";
const context = createContext(undefined);
@@ -11,7 +12,9 @@ export function RetromClientProvider(props: PropsWithChildren) {
const { children } = props;
const client = useMemo(() => {
- const host = hostname + (port ? `:${port}` : "");
+ const host = checkIsDesktop()
+ ? hostname + (port ? `:${port}` : "")
+ : "/api";
return new RetromClient(host);
}, [hostname, port]);
diff --git a/packages/client/web/vite.config.ts b/packages/client/web/vite.config.ts
index e49ccf64..0f6ac255 100644
--- a/packages/client/web/vite.config.ts
+++ b/packages/client/web/vite.config.ts
@@ -3,10 +3,32 @@ import react from "@vitejs/plugin-react";
import path from "path";
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
+const localServiceHost =
+ process.env.RETROM_LOCAL_SERVICE_HOST || "http://localhost:5101";
+
// https://vitejs.dev/config/
export default defineConfig({
server: {
port: 3000,
+ host: "0.0.0.0",
+ proxy: {
+ "/api": {
+ target: localServiceHost,
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, ""),
+ },
+ },
+ },
+ preview: {
+ port: 3000,
+ host: "0.0.0.0",
+ proxy: {
+ "/api": {
+ target: localServiceHost,
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, ""),
+ },
+ },
},
plugins: [TanStackRouterVite(), react()],
resolve: {