mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-02 11:36:01 +01:00
🐳 Fix issues with dockerfile (#1611)
* Add `wait $PID` to be able to send SIG_ABORT * Move to docker `entrypoint` * Change default NEXTAUTH_URL * Add `VOLUME` instruction * corrected a typo * 🐳 Fix docker TCP not working Fixes Lost docker connection via TCP with 0.14.0 update #1577 * 🚧 Improve dockerfile and start script and fix permission issue by adding new user with permission to read / write to /data folder * 🐛 Cleanup changes, Local db:migrate script not working, CI failed * ✨ Image properties customization (#1590) * 🌐 New Crowdin updates (#1572) * ✨ Add notice page for readonly db * Misc docker changes * 🐳 Add `homarr` as `USER` * 🐛 Unable to use user homarr because db.sqlite file is already owned by root --------- Co-authored-by: Lumilias <10852161+Lumilias@users.noreply.github.com> Co-authored-by: Meier Lukas <meierschlumpf@gmail.com> Co-authored-by: Manuel <30572287+manuel-rw@users.noreply.github.com> Co-authored-by: Manuel <manuel.ruwe@bluewin.ch>
This commit is contained in:
16
Dockerfile
16
Dockerfile
@@ -1,11 +1,6 @@
|
||||
FROM node:20.5-slim
|
||||
WORKDIR /app
|
||||
|
||||
ARG UID=1001
|
||||
ARG GID=1001
|
||||
RUN groupadd -g $GID homarr-group
|
||||
RUN useradd -r -u $UID -g $GID homarr
|
||||
|
||||
# Define node.js environment variables
|
||||
ARG PORT=7575
|
||||
|
||||
@@ -28,10 +23,9 @@ COPY ./drizzle/migrate ./migrate
|
||||
COPY ./tsconfig.json ./migrate/tsconfig.json
|
||||
|
||||
RUN mkdir /data
|
||||
RUN chown -R homarr:homarr-group /data
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update -y && apt-get install -y openssl wget
|
||||
RUN apt update && apt install -y openssl wget
|
||||
|
||||
# Move node_modules to temp location to avoid overwriting
|
||||
RUN mv node_modules _node_modules
|
||||
@@ -54,13 +48,13 @@ EXPOSE $PORT
|
||||
ENV PORT=${PORT}
|
||||
|
||||
ENV DATABASE_URL "file:/data/db.sqlite"
|
||||
ENV NEXTAUTH_URL "http://localhost:3000"
|
||||
ENV NEXTAUTH_URL "http://localhost:7575"
|
||||
ENV PORT 7575
|
||||
ENV NEXTAUTH_SECRET NOT_IN_USE_BECAUSE_JWTS_ARE_UNUSED
|
||||
|
||||
HEALTHCHECK --interval=10s --timeout=5s --start-period=5s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT} || exit 1
|
||||
|
||||
USER homarr
|
||||
|
||||
CMD ["sh", "./scripts/run.sh"]
|
||||
VOLUME [ "/app/data/configs" ]
|
||||
VOLUME [ "/data" ]
|
||||
ENTRYPOINT ["sh", "./scripts/run.sh"]
|
||||
|
||||
513
data/default.json
Normal file
513
data/default.json
Normal file
@@ -0,0 +1,513 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"configProperties": {
|
||||
"name": "default"
|
||||
},
|
||||
"categories": [],
|
||||
"wrappers": [
|
||||
{
|
||||
"id": "default",
|
||||
"position": 0
|
||||
}
|
||||
],
|
||||
"apps": [
|
||||
{
|
||||
"id": "5df743d9-5cb1-457c-85d2-64ff86855652",
|
||||
"name": "Documentation",
|
||||
"url": "https://homarr.dev",
|
||||
"behaviour": {
|
||||
"onClickUrl": "https://homarr.dev",
|
||||
"externalUrl": "https://homarr.dev",
|
||||
"isOpeningNewTab": true
|
||||
},
|
||||
"network": {
|
||||
"enabledStatusChecker": false,
|
||||
"statusCodes": [
|
||||
"200"
|
||||
]
|
||||
},
|
||||
"appearance": {
|
||||
"iconUrl": "/imgs/logo/logo.png",
|
||||
"appNameStatus": "normal",
|
||||
"positionAppName": "column",
|
||||
"lineClampAppName": 1
|
||||
},
|
||||
"integration": {
|
||||
"type": null,
|
||||
"properties": []
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 5,
|
||||
"y": 1
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 2
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 6,
|
||||
"y": 1
|
||||
},
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a337",
|
||||
"name": "Discord",
|
||||
"url": "https://discord.com/invite/aCsmEV5RgA",
|
||||
"behaviour": {
|
||||
"onClickUrl": "https://discord.com/invite/aCsmEV5RgA",
|
||||
"isOpeningNewTab": true,
|
||||
"externalUrl": "https://discord.com/invite/aCsmEV5RgA",
|
||||
"tooltipDescription": "Join our Discord server! We're waiting for your ideas and feedback. "
|
||||
},
|
||||
"network": {
|
||||
"enabledStatusChecker": false,
|
||||
"statusCodes": [
|
||||
"200"
|
||||
]
|
||||
},
|
||||
"appearance": {
|
||||
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/discord.png",
|
||||
"appNameStatus": "normal",
|
||||
"positionAppName": "row-reverse",
|
||||
"lineClampAppName": 1
|
||||
},
|
||||
"integration": {
|
||||
"type": null,
|
||||
"properties": []
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 1,
|
||||
"y": 4
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 4,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330",
|
||||
"name": "Contribute",
|
||||
"url": "https://github.com/ajnart/homarr",
|
||||
"behaviour": {
|
||||
"onClickUrl": "https://github.com/ajnart/homarr",
|
||||
"externalUrl": "https://github.com/ajnart/homarr",
|
||||
"isOpeningNewTab": true,
|
||||
"tooltipDescription": ""
|
||||
},
|
||||
"network": {
|
||||
"enabledStatusChecker": false,
|
||||
"statusCodes": []
|
||||
},
|
||||
"appearance": {
|
||||
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/github.png",
|
||||
"appNameStatus": "normal",
|
||||
"positionAppName": "row-reverse",
|
||||
"lineClampAppName": 2
|
||||
},
|
||||
"integration": {
|
||||
"type": null,
|
||||
"properties": []
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 1,
|
||||
"y": 3
|
||||
},
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990",
|
||||
"name": "Donate",
|
||||
"url": "https://ko-fi.com/ajnart",
|
||||
"behaviour": {
|
||||
"onClickUrl": "https://ko-fi.com/ajnart",
|
||||
"externalUrl": "https://ko-fi.com/ajnart",
|
||||
"isOpeningNewTab": true,
|
||||
"tooltipDescription": "Please consider making a donation"
|
||||
},
|
||||
"network": {
|
||||
"enabledStatusChecker": false,
|
||||
"statusCodes": [
|
||||
"200"
|
||||
]
|
||||
},
|
||||
"appearance": {
|
||||
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/ko-fi.png",
|
||||
"appNameStatus": "normal",
|
||||
"positionAppName": "row-reverse",
|
||||
"lineClampAppName": 1
|
||||
},
|
||||
"integration": {
|
||||
"type": null,
|
||||
"properties": []
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 4,
|
||||
"y": 1
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 2,
|
||||
"y": 4
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 6,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"widgets": [
|
||||
{
|
||||
"id": "e3004052-6b83-480e-b458-56e8ccdca5f0",
|
||||
"type": "weather",
|
||||
"properties": {
|
||||
"displayInFahrenheit": false,
|
||||
"location": {
|
||||
"name": "Paris",
|
||||
"latitude": 48.85341,
|
||||
"longitude": 2.3488
|
||||
},
|
||||
"displayCityName": true
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 5,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "971aa859-8570-49a1-8d34-dd5c7b3638d1",
|
||||
"type": "date",
|
||||
"properties": {
|
||||
"display24HourFormat": true,
|
||||
"dateFormat": "hide",
|
||||
"enableTimezone": false,
|
||||
"timezoneLocation": {
|
||||
"name": "Paris",
|
||||
"latitude": 48.85341,
|
||||
"longitude": 2.3488
|
||||
},
|
||||
"titleState": "city"
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 1,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 4,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 8,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "f252768d-9e69-491b-b6b4-8cad04fa30e8",
|
||||
"type": "date",
|
||||
"properties": {
|
||||
"display24HourFormat": true,
|
||||
"dateFormat": "hide",
|
||||
"enableTimezone": true,
|
||||
"timezoneLocation": {
|
||||
"name": "Tokyo",
|
||||
"latitude": 35.6895,
|
||||
"longitude": 139.69171
|
||||
},
|
||||
"titleState": "city"
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 3,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 1,
|
||||
"height": 1
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 8,
|
||||
"y": 1
|
||||
},
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "86b1921f-efa7-410f-92dd-79553bf3264d",
|
||||
"type": "notebook",
|
||||
"properties": {
|
||||
"showToolbar": true,
|
||||
"content": "<h2><strong>Welcome to Homarr 🚀👋</strong></h2><p>We're glad that you're here! Homarr is a <em>modern </em>and <em>easy to use</em> dashboard that helps you to <strong>organize and manage</strong> your home network from one place. Control is <strong>at your fingertips</strong>.</p><p>We recommend you to read the <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://homarr.dev/docs/introduction/after-the-installation\">getting started guide</a> first. To edit this board you must enter the edit mode - only administrators can do this. Adding an app is the first step you should take. You can do this by clicking the <code>Add tile</code> button at the top right and select <code>App</code>. After you provided an internal URL, external URL and selected an icon you can drag it around when holding down the left mouse button. Make it bigger or smaller using the drag icon at the bottom right. When you're happy with it's position, you <strong>must exit edit mode to save your board</strong>. Adding widgets works the same way but may require additional configuration - read the documentation for more information.</p><p>To remove this widget, you must log in to your administrator account and click on the menu to delete it.</p><p><strong><u>Your TODO list:</u></strong></p><ul data-type=\"taskList\"><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Read the <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://homarr.dev\">documentation</a></p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Add your <em>first app</em></p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p><em>Resize </em>and <em>drag</em> your app to a different position</p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Add the <em>clock widget</em> to your dashboard</p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Create a <em>new user</em></p></div></li></ul>"
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 3,
|
||||
"height": 2
|
||||
}
|
||||
},
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 3,
|
||||
"height": 4
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
"size": {
|
||||
"width": 6,
|
||||
"height": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"common": {
|
||||
"searchEngine": {
|
||||
"type": "google",
|
||||
"properties": {}
|
||||
}
|
||||
},
|
||||
"customization": {
|
||||
"layout": {
|
||||
"enabledLeftSidebar": false,
|
||||
"enabledRightSidebar": false,
|
||||
"enabledDocker": false,
|
||||
"enabledPing": false,
|
||||
"enabledSearchbar": true
|
||||
},
|
||||
"pageTitle": "Homarr ⭐️",
|
||||
"logoImageUrl": "/imgs/logo/logo.png",
|
||||
"faviconUrl": "/imgs/favicon/favicon-squared.png",
|
||||
"backgroundImageUrl": "",
|
||||
"customCss": "",
|
||||
"colors": {
|
||||
"primary": "red",
|
||||
"secondary": "yellow",
|
||||
"shade": 7
|
||||
},
|
||||
"appOpacity": 100,
|
||||
"gridstack": {
|
||||
"columnCountSmall": 3,
|
||||
"columnCountMedium": 6,
|
||||
"columnCountLarge": 10
|
||||
}
|
||||
},
|
||||
"access": {
|
||||
"allowGuests": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,4 +9,6 @@ cd ./migrate; yarn db:migrate & PID=$!
|
||||
wait $PID
|
||||
|
||||
echo "Starting production server..."
|
||||
node /app/server.js
|
||||
node /app/server.js & PID=$!
|
||||
|
||||
wait $PID
|
||||
42
src/components/Onboarding/database-not-writeable.tsx
Normal file
42
src/components/Onboarding/database-not-writeable.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Center, Code, List, Stack, Text, Title } from '@mantine/core';
|
||||
import Head from 'next/head';
|
||||
|
||||
export const DatabaseNotWriteable = ({ error, errorMessage }: { error: any | unknown, errorMessage: string | undefined }) => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Onboard - Error • Homarr</title>
|
||||
</Head>
|
||||
|
||||
<Center h="100%">
|
||||
<Stack align="center" p="lg">
|
||||
<Title order={1} weight={800} size="3rem" opacity={0.8}>
|
||||
Critical error while starting Homarr
|
||||
</Title>
|
||||
<Text size="lg" mb={40}>
|
||||
We detected that Homarr is unable to write to the database. Please troubleshoot using
|
||||
the following steps:
|
||||
</Text>
|
||||
<List>
|
||||
<List.Item>
|
||||
Ensure that you mounted the path <code>/data</code> to a writeable location with
|
||||
enough disk space. For this, you must add the following mounting point to your docker
|
||||
compose: <Code block>{' - <your-path>/data:/data'}</Code>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
Ensure that you followed the installation instructions at{' '}
|
||||
<a href="https://homarr.dev/docs/introduction/installation">
|
||||
https://homarr.dev/docs/introduction/installation
|
||||
</a>
|
||||
</List.Item>
|
||||
</List>
|
||||
<Code block>{error && JSON.stringify(error)}</Code>
|
||||
|
||||
{errorMessage && (
|
||||
<Code block>{errorMessage}</Code>
|
||||
)}
|
||||
</Stack>
|
||||
</Center>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -47,11 +47,5 @@ const shouldRedirectToOnboard = async (): Promise<boolean> => {
|
||||
return cachedUserCount === 0;
|
||||
};
|
||||
|
||||
if (!process.env.DATABASE_URL?.startsWith('file:')) {
|
||||
return await cacheAndGetUserCount();
|
||||
}
|
||||
|
||||
const fileUri = process.env.DATABASE_URL.substring(4);
|
||||
return await cacheAndGetUserCount();
|
||||
// TODO: Show an error page if the database file is read-only
|
||||
};
|
||||
|
||||
@@ -1,19 +1,28 @@
|
||||
import { Box, Button, Center, Image, Stack, Text, Title, useMantineTheme } from '@mantine/core';
|
||||
import { Button, Center, Image, Stack, Text, Title, useMantineTheme } from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { IconArrowRight } from '@tabler/icons-react';
|
||||
import Consola from 'consola';
|
||||
import fs from 'fs';
|
||||
import fsPromises from 'fs/promises';
|
||||
import { GetServerSideProps, InferGetServerSidePropsType } from 'next';
|
||||
import Head from 'next/head';
|
||||
import { DatabaseNotWriteable } from '~/components/Onboarding/database-not-writeable';
|
||||
import { OnboardingSteps } from '~/components/Onboarding/onboarding-steps';
|
||||
import { ThemeSchemeToggle } from '~/components/ThemeSchemeToggle/ThemeSchemeToggle';
|
||||
import { FloatingBackground } from '~/components/layout/Background/FloatingBackground';
|
||||
import { db } from '~/server/db';
|
||||
import { env } from '~/env';
|
||||
import { getTotalUserCountAsync } from '~/server/db/queries/user';
|
||||
import { getConfig } from '~/tools/config/getConfig';
|
||||
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
|
||||
|
||||
const util = require('util');
|
||||
const exec = util.promisify(require('child_process').exec);
|
||||
|
||||
export default function OnboardPage({
|
||||
configSchemaVersions,
|
||||
databaseNotWriteable,
|
||||
error,
|
||||
errorMessage
|
||||
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||
const { fn, colors, colorScheme } = useMantineTheme();
|
||||
const background = colorScheme === 'dark' ? 'dark.6' : 'gray.1';
|
||||
@@ -39,29 +48,35 @@ export default function OnboardPage({
|
||||
</Center>
|
||||
</Center>
|
||||
|
||||
{onboardingSteps ? (
|
||||
<OnboardingSteps isUpdate={isUpgradeFromSchemaOne} />
|
||||
{databaseNotWriteable == true ? (
|
||||
<DatabaseNotWriteable error={error} errorMessage={errorMessage} />
|
||||
) : (
|
||||
<Center h="100%">
|
||||
<Stack align="center" p="lg">
|
||||
<Title order={1} weight={800} size="3rem" opacity={0.8}>
|
||||
Welcome to Homarr!
|
||||
</Title>
|
||||
<Text size="lg" mb={40}>
|
||||
Your favorite dashboard has received a big upgrade.
|
||||
<br />
|
||||
We'll help you update within the next few steps
|
||||
</Text>
|
||||
<>
|
||||
{onboardingSteps ? (
|
||||
<OnboardingSteps isUpdate={isUpgradeFromSchemaOne} />
|
||||
) : (
|
||||
<Center h="100%">
|
||||
<Stack align="center" p="lg">
|
||||
<Title order={1} weight={800} size="3rem" opacity={0.8}>
|
||||
Welcome to Homarr!
|
||||
</Title>
|
||||
<Text size="lg" mb={40}>
|
||||
Your favorite dashboard has received a big upgrade.
|
||||
<br />
|
||||
We'll help you update within the next few steps
|
||||
</Text>
|
||||
|
||||
<Button
|
||||
onClick={showOnboardingSteps}
|
||||
rightIcon={<IconArrowRight size="1rem" />}
|
||||
variant="default"
|
||||
>
|
||||
Start update process
|
||||
</Button>
|
||||
</Stack>
|
||||
</Center>
|
||||
<Button
|
||||
onClick={showOnboardingSteps}
|
||||
rightIcon={<IconArrowRight size="1rem" />}
|
||||
variant="default"
|
||||
>
|
||||
Start update process
|
||||
</Button>
|
||||
</Stack>
|
||||
</Center>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</>
|
||||
@@ -87,10 +102,65 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
||||
ctx.res
|
||||
);
|
||||
|
||||
if (env.DATABASE_URL.startsWith('file:')) {
|
||||
const rawDatabaseUrl = env.DATABASE_URL.substring('file:'.length);
|
||||
Consola.info(
|
||||
`Instance is using a database on the file system. Checking if file '${rawDatabaseUrl}' is writable...`
|
||||
);
|
||||
try {
|
||||
await fsPromises.access(rawDatabaseUrl, fs.constants.W_OK);
|
||||
} catch (error) {
|
||||
// this usually occurs when the database path is not mounted in Docker
|
||||
Consola.error(`Database '${rawDatabaseUrl}' is not writable.`, error);
|
||||
return {
|
||||
props: {
|
||||
...translations,
|
||||
configSchemaVersions: configSchemaVersions,
|
||||
databaseNotWriteable: true,
|
||||
error: error,
|
||||
},
|
||||
};
|
||||
}
|
||||
Consola.info('Database is writeable');
|
||||
|
||||
if (process.platform !== 'win32') {
|
||||
try {
|
||||
const { stdout, stderr } = await exec("mount | grep '/data'");
|
||||
|
||||
if (stderr.split('\n').length > 1 || stdout.split('\n').length <= 1) {
|
||||
Consola.error(`Database at '${rawDatabaseUrl}' has not been mounted: ${stdout.replace('\n', '\\n')} ${stderr.replace('\n', '\\n')}`);
|
||||
return {
|
||||
props: {
|
||||
...translations,
|
||||
configSchemaVersions: configSchemaVersions,
|
||||
databaseNotWriteable: true,
|
||||
error: `Database at '${rawDatabaseUrl}' is not mounted:\n${stdout}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMessage = `Database at '${rawDatabaseUrl}' has not been mounted: ${error}`;
|
||||
Consola.error(errorMessage);
|
||||
return {
|
||||
props: {
|
||||
...translations,
|
||||
configSchemaVersions: configSchemaVersions,
|
||||
databaseNotWriteable: true,
|
||||
error: error,
|
||||
errorMessage: errorMessage
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Consola.info(`Database at '${rawDatabaseUrl}' is writeable and mounted`);
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
...translations,
|
||||
configSchemaVersions: configSchemaVersions,
|
||||
databaseNotWriteable: false
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ConfigType } from '~/types/config';
|
||||
|
||||
import defaultConfig from '../../../data/configs/default.json';
|
||||
import defaultConfig from '../../../data/default.json';
|
||||
|
||||
export const getFallbackConfig = (name?: string) => ({
|
||||
...defaultConfig,
|
||||
|
||||
Reference in New Issue
Block a user