Merge branch 'master' into develop

This commit is contained in:
Nicolas Meienberger 2022-10-23 10:14:29 +02:00
commit fda8a4d824
28 changed files with 354 additions and 126 deletions

View file

@ -128,6 +128,24 @@
"contributions": [
"code"
]
},
{
"login": "iBicha",
"name": "Brahim Hadriche",
"avatar_url": "https://avatars.githubusercontent.com/u/17722782?v=4",
"profile": "https://github.com/iBicha",
"contributions": [
"code"
]
},
{
"login": "andrewbrereton",
"name": "Andrew Brereton",
"avatar_url": "https://avatars.githubusercontent.com/u/682893?v=4",
"profile": "https://andrewbrereton.com",
"contributions": [
"content"
]
}
],
"contributorsPerLine": 7,
@ -135,5 +153,6 @@
"projectOwner": "meienberger",
"repoType": "github",
"repoHost": "https://github.com",
"skipCi": true
"skipCi": true,
"commitConvention": "angular"
}

View file

@ -5,5 +5,8 @@
node_modules
.next
dist/
**/dist/
**/next/
# all docker-compose files
docker-compose*.yml
Dockerfile*
.dockerignore

2
.github/FUNDING.yml vendored
View file

@ -6,7 +6,7 @@ open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
liberapay: meienberger # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry

View file

@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:latest
image: postgres:14
env:
POSTGRES_PASSWORD: postgres
ports:

1
.gitignore vendored
View file

@ -2,6 +2,7 @@
*.swp
.DS_Store
.vscode
logs
.pnpm-debug.log

View file

@ -1,5 +0,0 @@
{
"yaml.schemas": {
"https://raw.githubusercontent.com/ansible-community/schemas/main/f/ansible-playbook.json": "file:///Users/nicolas/Projects/runtipi/ansible/playbooks/install-dependencies.yml"
}
}

View file

@ -1,4 +1,4 @@
FROM node:18 AS build
FROM node:18 AS builder
RUN npm install node-gyp -g
@ -35,13 +35,13 @@ WORKDIR /api
COPY ./packages/system-api/package*.json /api/
RUN npm install --omit=dev
COPY --from=builder /api/dist /api/dist
WORKDIR /dashboard
COPY ./packages/dashboard/package*.json /dashboard/
RUN npm install --omit=dev
COPY --from=build /api/dist /api/dist
COPY --from=build /dashboard/.next /dashboard/.next
COPY ./packages/dashboard /dashboard
COPY --from=builder /dashboard/next.config.js ./
COPY --from=builder /dashboard/public ./public
COPY --from=builder /dashboard/package.json ./package.json
COPY --from=builder --chown=node:node /dashboard/.next/standalone ./
COPY --from=builder --chown=node:node /dashboard/.next/static ./.next/static
WORKDIR /

View file

@ -1,6 +1,6 @@
# ⛺️ Tipi — A personal homeserver for everyone
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-15-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
[![License](https://img.shields.io/github/license/meienberger/runtipi)](https://github.com/meienberger/runtipi/blob/master/LICENSE)
[![Version](https://img.shields.io/github/v/release/meienberger/runtipi?color=%235351FB&label=version)](https://github.com/meienberger/runtipi/releases)
@ -23,23 +23,32 @@ Check our demo instance : **[demo.runtipi.com](https://demo.runtipi.com)** / use
## Apps available
- [Adguard Home](https://github.com/AdguardTeam/AdGuardHome) - Adguard Home DNS adblocker
- [Booksonic](https://github.com/popeen) - A server for streaming your audiobooks
- [BookStack](https://www.bookstackapp.com/) - BookStack is a self-hosted platform for organising and storing information.
- [Calibre-Web](https://github.com/janeczku/calibre-web) - Web Ebook Reader
- [Code-Server](https://github.com/coder/code-server) - Web VS Code
- [Filebrowser](https://github.com/filebrowser/filebrowser) - Web File Browser
- [Firefly III](https://github.com/firefly-iii/firefly-iii) - A personal finances manager
- [Freshrss](https://github.com/FreshRSS/FreshRSS) - A free, self-hostable RSS aggregator
- [Gitea](https://github.com/go-gitea/gitea) - Gitea - A painless self-hosted Git service
- [FreshRSS](https://github.com/FreshRSS/FreshRSS) - A free, self-hostable RSS aggregator
- [Ghost](https://github.com/TryGhost/Ghost) - Ghost - Turn your audience into a business
- [Gitea](https://github.com/go-gitea/gitea) - Gitea - A painless self-hosted Git service
- [Gotify](https://github.com/gotify/server) - Simple server for sending and receiving notification messages.
- [Haven](https://github.com/havenweb/haven) - Haven is a self-hosted private blog and feedreader you can use instead of Facebook
- [Homarr](https://github.com/ajnart/homarr) - A homepage for your server
- [Home Assistant](https://github.com/home-assistant/core) - Open source home automation that puts local control and privacy first
- [Immich](https://www.immich.app/) - Photo and video backup solution directly from your mobile phone
- [Invidious](https://github.com/iv-org/invidious) - An alternative front-end to YouTube
- [Jackett](https://github.com/Jackett/Jackett) - API Support for your favorite torrent trackers
- [Jellyfin](https://github.com/jellyfin/jellyfin) - A media server for your home collection
- [Joplin](https://github.com/laurent22/joplin) - Privacy focused note-taking app
- [Libreddit](https://github.com/spikecodes/libreddit) - Private front-end for Reddit
- [Mealie](https://github.com/hay-kot/mealie) - Self-hosted recipe manager and meal planner.
- [LibrePhotos](https://github.com/LibrePhotos/librephotos) - A self-hosted open source photo management service
- [LibreTranslate](https://github.com/LibreTranslate/LibreTranslate) - Free and open source machine translation API
- [Lidarr](https://github.com/Lidarr/Lidarr) - Looks and smells like Sonarr but made for music
- [Mealie](https://github.com/hay-kot/mealie) - Self-hosted recipe manager and meal planner
- [MoneroBlock](https://github.com/duggavo/MoneroBlock) - Decentralized and trustless Monero block explorer
- [Monero Daemon](https://github.com/sethforprivacy/simple-monerod-docker) - Monero is a private, decentralized cryptocurrency that keeps your finances confidential and secure
- [n8n](https://github.com/n8n-io/n8n) - Workflow Automation Tool
- [Navidrome](https://github.com/navidrome/navidrome/) - Modern Music Server and Streamer compatible with Subsonic/Airsonic
- [Nextcloud](https://github.com/nextcloud/server) - A safe home for all your data
- [Nitter](https://github.com/zedeus/nitter) - Alternative Twitter front-end
- [Node-RED](https://github.com/node-red/node-red) - Low-code programming for event-driven applications
@ -47,18 +56,28 @@ Check our demo instance : **[demo.runtipi.com](https://demo.runtipi.com)** / use
- [Photoprism](https://github.com/photoprism/photoprism) - AI-Powered Photos App for the Decentralized Web. We are on a mission to protect your freedom and privacy.
- [Pihole](https://github.com/pi-hole/pi-hole) - A black hole for Internet advertisements
- [Plex](https://github.com/plexinc/pms-docker) - Stream Movies & TV Shows
- [Portainer](https://github.com/portainer/portainer) - Making Docker and Kubernetes management easy.
- [Portainer](https://github.com/portainer/portainer) - Making Docker and Kubernetes management easy
- [PrivateBin](https://github.com/PrivateBin/PrivateBin) - A minimalist, open source online pastebin where the server has zero knowledge of pasted data
- [Prowlarr](https://github.com/Prowlarr/Prowlarr/) - A torrent/usenet indexer manager/proxy
- [ProxiTok](https://github.com/pablouser1/ProxiTok) - Open source alternative frontend for TikTok made using PHP
- [qBittorrent](https://github.com/qbittorrent/qBittorrent) - Fast, easy, and free BitTorrent client
- [Radarr](https://github.com/Radarr/Radarr) - Movie collection manager for Usenet and BitTorrent users
- [Readarr](https://github.com/Readarr/Readarr) - Book Manager and Automation (Sonarr for Ebooks)
- [Resilio Sync](https://github.com/bt-sync) - Fast, reliable, and simple file sync and share solution
- [SearXNG](https://github.com/searxng/searxng) - Privacy-respecting, hackable metasearch engine
- [Send](https://gitlab.com/timvisee/send) - Simple, private file sharing
- [Sonarr](https://github.com/Sonarr/Sonarr) - TV show manager for Usenet and BitTorrent
- [Syncthing](https://github.com/syncthing/syncthing) - Continuous File Synchronization
- [Tailscale](https://github.com/tailscale/tailscale) - The easiest, most secure way to use WireGuard and 2FA
- [Tautulli](https://github.com/Tautulli/Tautulli) - A Python based monitoring and tracking tool for Plex Media Server
- [teddit](https://codeberg.org/teddit/teddit) - Alternative Reddit front-end focused on privacy
- [Transmission](https://github.com/transmission/transmission) - Fast, easy, and free BitTorrent client
- [Wireguard Easy](https://github.com/WeeJeWel/wg-easy) - WireGuard VPN + Web-based Admin UI
- [Tube Archivist](https://github.com/tubearchivist/tubearchivist) - Your self-hosted YouTube media server
- [Uptime Kuma](https://github.com/louislam/uptime-kuma) - A fancy self-hosted monitoring tool
- [Vaultwarden](https://github.com/dani-garcia/vaultwarden) - Unofficial Bitwarden compatible server
- [Wireguard Easy](https://github.com/WeeJeWel/wg-easy) - WireGuard VPN + Web-based Admin UI
- [Your Spotify](https://github.com/Yooooomi/your_spotify) - Self hosted Spotify tracking dashboard
- [Zerotier](https://www.zerotier.com) - Easy to use zero configuration VPN
You can find and submit new apps inside of the [RunTipi Appstore](https://github.com/meienberger/runtipi-appstore).
@ -150,21 +169,25 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<table>
<tbody>
<tr>
<td align="center"><a href="https://meienberger.dev/"><img src="https://avatars.githubusercontent.com/u/47644445?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nicolas Meienberger</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=meienberger" title="Code">💻</a> <a href="#infra-meienberger" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/meienberger/runtipi/commits?author=meienberger" title="Tests">⚠️</a> <a href="https://github.com/meienberger/runtipi/commits?author=meienberger" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/ArneNaessens"><img src="https://avatars.githubusercontent.com/u/16622722?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ArneNaessens</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=ArneNaessens" title="Code">💻</a> <a href="#ideas-ArneNaessens" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/meienberger/runtipi/commits?author=ArneNaessens" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/DrMxrcy"><img src="https://avatars.githubusercontent.com/u/58747968?v=4?s=100" width="100px;" alt=""/><br /><sub><b>DrMxrcy</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=DrMxrcy" title="Code">💻</a> <a href="#ideas-DrMxrcy" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/meienberger/runtipi/commits?author=DrMxrcy" title="Tests">⚠️</a></td>
<td align="center"><a href="https://cobre.dev"><img src="https://avatars.githubusercontent.com/u/36574329?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cooper</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=CobreDev" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/JTruj1ll0923"><img src="https://avatars.githubusercontent.com/u/6656643?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JTruj1ll0923</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=JTruj1ll0923" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Stetsed"><img src="https://avatars.githubusercontent.com/u/33891782?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stetsed</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=Stetsed" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/blushell"><img src="https://avatars.githubusercontent.com/u/3621606?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jones_Town</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=blushell" title="Code">💻</a></td>
<td align="center"><a href="https://meienberger.dev/"><img src="https://avatars.githubusercontent.com/u/47644445?v=4?s=100" width="100px;" alt="Nicolas Meienberger"/><br /><sub><b>Nicolas Meienberger</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=meienberger" title="Code">💻</a> <a href="#infra-meienberger" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/meienberger/runtipi/commits?author=meienberger" title="Tests">⚠️</a> <a href="https://github.com/meienberger/runtipi/commits?author=meienberger" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/ArneNaessens"><img src="https://avatars.githubusercontent.com/u/16622722?v=4?s=100" width="100px;" alt="ArneNaessens"/><br /><sub><b>ArneNaessens</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=ArneNaessens" title="Code">💻</a> <a href="#ideas-ArneNaessens" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/meienberger/runtipi/commits?author=ArneNaessens" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/DrMxrcy"><img src="https://avatars.githubusercontent.com/u/58747968?v=4?s=100" width="100px;" alt="DrMxrcy"/><br /><sub><b>DrMxrcy</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=DrMxrcy" title="Code">💻</a> <a href="#ideas-DrMxrcy" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/meienberger/runtipi/commits?author=DrMxrcy" title="Tests">⚠️</a></td>
<td align="center"><a href="https://cobre.dev"><img src="https://avatars.githubusercontent.com/u/36574329?v=4?s=100" width="100px;" alt="Cooper"/><br /><sub><b>Cooper</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=CobreDev" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/JTruj1ll0923"><img src="https://avatars.githubusercontent.com/u/6656643?v=4?s=100" width="100px;" alt="JTruj1ll0923"/><br /><sub><b>JTruj1ll0923</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=JTruj1ll0923" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Stetsed"><img src="https://avatars.githubusercontent.com/u/33891782?v=4?s=100" width="100px;" alt="Stetsed"/><br /><sub><b>Stetsed</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=Stetsed" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/blushell"><img src="https://avatars.githubusercontent.com/u/3621606?v=4?s=100" width="100px;" alt="Jones_Town"/><br /><sub><b>Jones_Town</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=blushell" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://rushichaudhari.github.io/"><img src="https://avatars.githubusercontent.com/u/6279035?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rushi Chaudhari</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=rushic24" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/rblaine95"><img src="https://avatars.githubusercontent.com/u/4052340?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robert Blaine</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=rblaine95" title="Code">💻</a></td>
<td align="center"><a href="https://sethforprivacy.com"><img src="https://avatars.githubusercontent.com/u/40500387?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Seth For Privacy</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=sethforprivacy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/hqwuzhaoyi"><img src="https://avatars.githubusercontent.com/u/44605072?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Prajna</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=hqwuzhaoyi" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/justincmoy"><img src="https://avatars.githubusercontent.com/u/14875982?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Justin Moy</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=justincmoy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/dextreem"><img src="https://avatars.githubusercontent.com/u/11060652?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dextreem</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=dextreem" title="Code">💻</a></td>
<td align="center"><a href="https://rushichaudhari.github.io/"><img src="https://avatars.githubusercontent.com/u/6279035?v=4?s=100" width="100px;" alt="Rushi Chaudhari"/><br /><sub><b>Rushi Chaudhari</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=rushic24" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/rblaine95"><img src="https://avatars.githubusercontent.com/u/4052340?v=4?s=100" width="100px;" alt="Robert Blaine"/><br /><sub><b>Robert Blaine</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=rblaine95" title="Code">💻</a></td>
<td align="center"><a href="https://sethforprivacy.com"><img src="https://avatars.githubusercontent.com/u/40500387?v=4?s=100" width="100px;" alt="Seth For Privacy"/><br /><sub><b>Seth For Privacy</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=sethforprivacy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/hqwuzhaoyi"><img src="https://avatars.githubusercontent.com/u/44605072?v=4?s=100" width="100px;" alt="Prajna"/><br /><sub><b>Prajna</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=hqwuzhaoyi" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/justincmoy"><img src="https://avatars.githubusercontent.com/u/14875982?v=4?s=100" width="100px;" alt="Justin Moy"/><br /><sub><b>Justin Moy</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=justincmoy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/dextreem"><img src="https://avatars.githubusercontent.com/u/11060652?v=4?s=100" width="100px;" alt="dextreem"/><br /><sub><b>dextreem</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=dextreem" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/iBicha"><img src="https://avatars.githubusercontent.com/u/17722782?v=4?s=100" width="100px;" alt="Brahim Hadriche"/><br /><sub><b>Brahim Hadriche</b></sub></a><br /><a href="https://github.com/meienberger/runtipi/commits?author=iBicha" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://andrewbrereton.com"><img src="https://avatars.githubusercontent.com/u/682893?v=4?s=100" width="100px;" alt="Andrew Brereton"/><br /><sub><b>Andrew Brereton</b></sub></a><br /><a href="#content-andrewbrereton" title="Content">🖋</a></td>
</tr>
</tbody>
</table>

View file

@ -20,7 +20,7 @@ services:
tipi-db:
container_name: tipi-db
image: postgres:latest
image: postgres:14
restart: on-failure
stop_grace_period: 1m
volumes:
@ -80,6 +80,7 @@ services:
APPS_REPO_ID: ${APPS_REPO_ID}
APPS_REPO_URL: ${APPS_REPO_URL}
DOMAIN: ${DOMAIN}
ARCHITECTURE: ${ARCHITECTURE}
networks:
- tipi_main_network
labels:

View file

@ -19,7 +19,7 @@ services:
tipi-db:
container_name: tipi-db
image: postgres:latest
image: postgres:14
restart: on-failure
stop_grace_period: 1m
volumes:
@ -72,6 +72,7 @@ services:
APPS_REPO_ID: ${APPS_REPO_ID}
APPS_REPO_URL: ${APPS_REPO_URL}
DOMAIN: ${DOMAIN}
ARCHITECTURE: ${ARCHITECTURE}
networks:
- tipi_main_network
labels:
@ -94,7 +95,7 @@ services:
dashboard:
image: meienberger/runtipi:rc-${TIPI_VERSION}
command: /bin/sh -c "cd /dashboard && npm run start"
command: /bin/sh -c "cd /dashboard && node server.js"
container_name: dashboard
networks:
- tipi_main_network

View file

@ -18,7 +18,7 @@ services:
tipi-db:
container_name: tipi-db
image: postgres:latest
image: postgres:14
restart: on-failure
stop_grace_period: 1m
volumes:
@ -72,6 +72,7 @@ services:
APPS_REPO_ID: ${APPS_REPO_ID}
APPS_REPO_URL: ${APPS_REPO_URL}
DOMAIN: ${DOMAIN}
ARCHITECTURE: ${ARCHITECTURE}
networks:
- tipi_main_network
labels:
@ -94,7 +95,7 @@ services:
dashboard:
image: meienberger/runtipi:${TIPI_VERSION}
command: /bin/sh -c "cd /dashboard && npm run start"
command: /bin/sh -c "cd /dashboard && node server.js"
restart: unless-stopped
container_name: dashboard
networks:

View file

@ -1,6 +1,6 @@
{
"name": "runtipi",
"version": "0.7.0",
"version": "0.7.1",
"description": "A homeserver for everyone",
"scripts": {
"prepare": "husky install",

View file

@ -1,7 +1,6 @@
/** @type {import('next').NextConfig} */
const { INTERNAL_IP, DOMAIN, NGINX_PORT } = process.env;
const nextConfig = {
output: 'standalone',
webpackDevMiddleware: (config) => {
config.watchOptions = {
poll: 1000,

View file

@ -1,6 +1,6 @@
{
"name": "dashboard",
"version": "0.7.0",
"version": "0.7.1",
"private": true,
"scripts": {
"test": "jest --colors",
@ -22,7 +22,7 @@
"framer-motion": "^6",
"graphql": "^15.8.0",
"graphql-tag": "^2.12.6",
"next": "12.1.6",
"next": "12.3.1",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-final-form": "^6.5.9",

View file

@ -1,6 +1,6 @@
{
"name": "system-api",
"version": "0.7.0",
"version": "0.7.1",
"description": "",
"exports": "./dist/server.js",
"type": "module",

View file

@ -2,6 +2,7 @@ import { z } from 'zod';
import * as dotenv from 'dotenv';
import fs from 'fs-extra';
import { readJsonFile } from '../../modules/fs/fs.helpers';
import { AppSupportedArchitecturesEnum } from '../../modules/apps/apps.types';
if (process.env.NODE_ENV !== 'production') {
dotenv.config({ path: '.env.dev' });
@ -22,12 +23,14 @@ const {
DOMAIN = '',
STORAGE_PATH = '/runtipi',
REDIS_HOST = 'tipi-redis',
ARCHITECTURE = 'amd64',
} = process.env;
const configSchema = z.object({
NODE_ENV: z.union([z.literal('development'), z.literal('production'), z.literal('test')]),
REDIS_HOST: z.string(),
status: z.union([z.literal('RUNNING'), z.literal('UPDATING'), z.literal('RESTARTING')]),
architecture: z.nativeEnum(AppSupportedArchitecturesEnum),
logs: z.object({
LOGS_FOLDER: z.string(),
LOGS_APP: z.string(),
@ -59,6 +62,7 @@ class Config {
},
REDIS_HOST,
NODE_ENV: NODE_ENV as z.infer<typeof configSchema>['NODE_ENV'],
architecture: ARCHITECTURE as z.infer<typeof configSchema>['architecture'],
rootFolder: '/runtipi',
internalIp: INTERNAL_IP,
version: TIPI_VERSION,

View file

@ -1,5 +1,5 @@
import { faker } from '@faker-js/faker';
import { AppCategoriesEnum, AppInfo, AppStatusEnum, FieldTypes } from '../apps.types';
import { AppCategoriesEnum, AppInfo, AppStatusEnum, AppSupportedArchitecturesEnum, FieldTypes } from '../apps.types';
import App from '../app.entity';
interface IProps {
@ -10,10 +10,11 @@ interface IProps {
exposed?: boolean;
domain?: string;
exposable?: boolean;
supportedArchitectures?: AppSupportedArchitecturesEnum[];
}
const createApp = async (props: IProps) => {
const { installed = false, status = AppStatusEnum.RUNNING, requiredPort, randomField = false, exposed = false, domain = '', exposable = false } = props;
const { installed = false, status = AppStatusEnum.RUNNING, requiredPort, randomField = false, exposed = false, domain = '', exposable = false, supportedArchitectures } = props;
const categories = Object.values(AppCategoriesEnum);
@ -29,6 +30,7 @@ const createApp = async (props: IProps) => {
env_variable: 'TEST_FIELD',
},
],
name: faker.random.word(),
description: faker.random.words(),
tipi_version: faker.datatype.number({ min: 1, max: 10 }),
@ -37,6 +39,7 @@ const createApp = async (props: IProps) => {
source: faker.internet.url(),
categories: [categories[faker.datatype.number({ min: 0, max: categories.length - 1 })]],
exposable,
supported_architectures: supportedArchitectures,
};
if (randomField) {

View file

@ -1,12 +1,13 @@
import AppsService from '../apps.service';
import fs from 'fs-extra';
import { AppInfo, AppStatusEnum } from '../apps.types';
import { AppInfo, AppStatusEnum, AppSupportedArchitecturesEnum } from '../apps.types';
import App from '../app.entity';
import { createApp } from './apps.factory';
import { setupConnection, teardownConnection } from '../../../test/connection';
import { DataSource } from 'typeorm';
import { getEnvMap } from '../apps.helpers';
import EventDispatcher, { eventDispatcher, EventTypes } from '../../../core/config/EventDispatcher';
import { setConfig } from '../../../core/config/TipiConfig';
jest.mock('fs-extra');
jest.mock('child_process');
@ -152,6 +153,38 @@ describe('Install app', () => {
await expect(AppsService.installApp(app3.appInfo.id, { TEST_FIELD: 'test' }, true, 'test.com')).rejects.toThrowError(`Domain test.com already in use by app ${app2.appInfo.id}`);
});
it('Should throw if architecure is not supported', async () => {
const { MockFiles, appInfo } = await createApp({ supportedArchitectures: [AppSupportedArchitecturesEnum.ARM] });
// @ts-ignore
fs.__createMockFiles(MockFiles);
await expect(AppsService.installApp(appInfo.id, { TEST_FIELD: 'test' })).rejects.toThrowError(`App ${appInfo.id} is not supported on this architecture`);
});
it('Can install if architecture is supported', async () => {
setConfig('architecture', AppSupportedArchitecturesEnum.ARM);
const { MockFiles, appInfo } = await createApp({ supportedArchitectures: [AppSupportedArchitecturesEnum.ARM, AppSupportedArchitecturesEnum.ARM64] });
// @ts-ignore
fs.__createMockFiles(MockFiles);
await AppsService.installApp(appInfo.id, { TEST_FIELD: 'test' });
const app = await App.findOne({ where: { id: appInfo.id } });
expect(app).toBeDefined();
});
it('Can install if no architecture is specified', async () => {
setConfig('architecture', AppSupportedArchitecturesEnum.ARM);
const { MockFiles, appInfo } = await createApp({ supportedArchitectures: undefined });
// @ts-ignore
fs.__createMockFiles(MockFiles);
await AppsService.installApp(appInfo.id, { TEST_FIELD: 'test' });
const app = await App.findOne({ where: { id: appInfo.id } });
expect(app).toBeDefined();
});
});
describe('Uninstall app', () => {
@ -431,6 +464,50 @@ describe('List apps', () => {
expect(apps[1].id).toBe(sortedApps[1].id);
expect(apps[0].description).toBe('md desc');
});
it('Should not list apps that have supportedArchitectures and are not supported', async () => {
// Arrange
setConfig('architecture', AppSupportedArchitecturesEnum.ARM64);
const app3 = await createApp({ supportedArchitectures: [AppSupportedArchitecturesEnum.ARM] });
// @ts-ignore
fs.__createMockFiles(Object.assign(app3.MockFiles));
// Act
const { apps } = await AppsService.listApps();
// Assert
expect(apps).toBeDefined();
expect(apps.length).toBe(0);
});
it('Should list apps that have supportedArchitectures and are supported', async () => {
// Arrange
setConfig('architecture', AppSupportedArchitecturesEnum.ARM);
const app3 = await createApp({ supportedArchitectures: [AppSupportedArchitecturesEnum.ARM] });
// @ts-ignore
fs.__createMockFiles(Object.assign(app3.MockFiles));
// Act
const { apps } = await AppsService.listApps();
// Assert
expect(apps).toBeDefined();
expect(apps.length).toBe(1);
});
it('Should list apps that have no supportedArchitectures specified', async () => {
// Arrange
setConfig('architecture', AppSupportedArchitecturesEnum.ARM);
const app3 = await createApp({});
// @ts-ignore
fs.__createMockFiles(Object.assign(app3.MockFiles));
// Act
const { apps } = await AppsService.listApps();
// Assert
expect(apps).toBeDefined();
expect(apps.length).toBe(1);
});
});
describe('Start all apps', () => {

View file

@ -26,6 +26,10 @@ export const checkAppRequirements = async (appName: string) => {
}
}
if (configFile?.supported_architectures && !configFile.supported_architectures.includes(getConfig().architecture)) {
throw new Error(`App ${appName} is not supported on this architecture`);
}
return valid;
};

View file

@ -9,6 +9,18 @@ import { getConfig } from '../../core/config/TipiConfig';
import { eventDispatcher, EventTypes } from '../../core/config/EventDispatcher';
const sortApps = (a: AppInfo, b: AppInfo) => a.name.localeCompare(b.name);
const filterApp = (app: AppInfo): boolean => {
if (!app.supported_architectures) {
return true;
}
const arch = getConfig().architecture;
return app.supported_architectures.includes(arch);
};
const filterApps = (apps: AppInfo[]): AppInfo[] => {
return apps.sort(sortApps).filter(filterApp);
};
/**
* Start all apps which had the status RUNNING in the database
@ -159,7 +171,7 @@ const listApps = async (): Promise<ListAppsResonse> => {
app.description = readFile(`/runtipi/repos/${getConfig().appsRepoId}/apps/${app.id}/metadata/description.md`);
});
return { apps: apps.sort(sortApps), total: apps.length };
return { apps: filterApps(apps), total: apps.length };
};
/**

View file

@ -41,6 +41,12 @@ export enum AppStatusEnum {
UPDATING = 'updating',
}
export enum AppSupportedArchitecturesEnum {
ARM = 'arm',
ARM64 = 'arm64',
AMD64 = 'amd64',
}
registerEnumType(AppCategoriesEnum, {
name: 'AppCategoriesEnum',
});
@ -49,6 +55,10 @@ registerEnumType(FieldTypes, {
name: 'FieldTypesEnum',
});
registerEnumType(AppSupportedArchitecturesEnum, {
name: 'AppSupportedArchitecturesEnum',
});
@ObjectType()
class FormField {
@Field(() => FieldTypes)
@ -128,6 +138,9 @@ class AppInfo {
@Field(() => Boolean, { nullable: true })
exposable?: boolean;
@Field(() => [AppSupportedArchitecturesEnum], { nullable: true })
supported_architectures?: AppSupportedArchitecturesEnum[];
}
@ObjectType()

View file

@ -85,6 +85,7 @@ const main = async () => {
// Start apps
appsService.startAllApps();
logger.info(`Server running on port ${port} 🚀 Production => ${__prod__}`);
logger.info(`Config: ${JSON.stringify(getConfig(), null, 2)}`);
});
} catch (error) {
logger.error(error);

View file

@ -49,7 +49,7 @@ importers:
graphql: ^15.8.0
graphql-tag: ^2.12.6
jest: ^28.1.0
next: 12.1.6
next: 12.3.1
postcss: ^8.4.12
react: 18.1.0
react-dom: 18.1.0
@ -78,7 +78,7 @@ importers:
framer-motion: 6.3.3_ef5jwxihqo6n7gxfmzogljlgcm
graphql: 15.8.0
graphql-tag: 2.12.6_graphql@15.8.0
next: 12.1.6_talmm3uuvp6ssixt2qevhfgvue
next: 12.3.1_talmm3uuvp6ssixt2qevhfgvue
react: 18.1.0
react-dom: 18.1.0_react@18.1.0
react-final-form: 6.5.9_bnxchjdfy45cdln7bu7hnhf37u
@ -109,7 +109,7 @@ importers:
autoprefixer: 10.4.7_postcss@8.4.13
eslint: 8.12.0
eslint-config-airbnb-typescript: 17.0.0_r46exuh3jlhq2wmrnqx2ufqspa
eslint-config-next: 12.1.4_e6a2zi6fqdwfehht5cxvkmo3zu
eslint-config-next: 12.1.4_c2ous3fcmy6f3xlzfnkf2jzbvm
eslint-plugin-import: 2.26.0_hhyjdrupy4c2vgtpytri6cjwoy
jest: 28.1.0_@types+node@17.0.31
postcss: 8.4.13
@ -3171,8 +3171,8 @@ packages:
graphql: 15.8.0
dev: true
/@next/env/12.1.6:
resolution: {integrity: sha512-Te/OBDXFSodPU6jlXYPAXpmZr/AkG6DCATAxttQxqOWaq6eDFX25Db3dK0120GZrSZmv4QCe9KsZmJKDbWs4OA==}
/@next/env/12.3.1:
resolution: {integrity: sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg==}
dev: false
/@next/eslint-plugin-next/12.1.4:
@ -3181,8 +3181,8 @@ packages:
glob: 7.1.7
dev: true
/@next/swc-android-arm-eabi/12.1.6:
resolution: {integrity: sha512-BxBr3QAAAXWgk/K7EedvzxJr2dE014mghBSA9iOEAv0bMgF+MRq4PoASjuHi15M2zfowpcRG8XQhMFtxftCleQ==}
/@next/swc-android-arm-eabi/12.3.1:
resolution: {integrity: sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ==}
engines: {node: '>= 10'}
cpu: [arm]
os: [android]
@ -3190,8 +3190,8 @@ packages:
dev: false
optional: true
/@next/swc-android-arm64/12.1.6:
resolution: {integrity: sha512-EboEk3ROYY7U6WA2RrMt/cXXMokUTXXfnxe2+CU+DOahvbrO8QSWhlBl9I9ZbFzJx28AGB9Yo3oQHCvph/4Lew==}
/@next/swc-android-arm64/12.3.1:
resolution: {integrity: sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
@ -3199,8 +3199,8 @@ packages:
dev: false
optional: true
/@next/swc-darwin-arm64/12.1.6:
resolution: {integrity: sha512-P0EXU12BMSdNj1F7vdkP/VrYDuCNwBExtRPDYawgSUakzi6qP0iKJpya2BuLvNzXx+XPU49GFuDC5X+SvY0mOw==}
/@next/swc-darwin-arm64/12.3.1:
resolution: {integrity: sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
@ -3208,8 +3208,8 @@ packages:
dev: false
optional: true
/@next/swc-darwin-x64/12.1.6:
resolution: {integrity: sha512-9FptMnbgHJK3dRDzfTpexs9S2hGpzOQxSQbe8omz6Pcl7rnEp9x4uSEKY51ho85JCjL4d0tDLBcXEJZKKLzxNg==}
/@next/swc-darwin-x64/12.3.1:
resolution: {integrity: sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
@ -3217,8 +3217,17 @@ packages:
dev: false
optional: true
/@next/swc-linux-arm-gnueabihf/12.1.6:
resolution: {integrity: sha512-PvfEa1RR55dsik/IDkCKSFkk6ODNGJqPY3ysVUZqmnWMDSuqFtf7BPWHFa/53znpvVB5XaJ5Z1/6aR5CTIqxPw==}
/@next/swc-freebsd-x64/12.3.1:
resolution: {integrity: sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [freebsd]
requiresBuild: true
dev: false
optional: true
/@next/swc-linux-arm-gnueabihf/12.3.1:
resolution: {integrity: sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
@ -3226,8 +3235,8 @@ packages:
dev: false
optional: true
/@next/swc-linux-arm64-gnu/12.1.6:
resolution: {integrity: sha512-53QOvX1jBbC2ctnmWHyRhMajGq7QZfl974WYlwclXarVV418X7ed7o/EzGY+YVAEKzIVaAB9JFFWGXn8WWo0gQ==}
/@next/swc-linux-arm64-gnu/12.3.1:
resolution: {integrity: sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@ -3235,8 +3244,8 @@ packages:
dev: false
optional: true
/@next/swc-linux-arm64-musl/12.1.6:
resolution: {integrity: sha512-CMWAkYqfGdQCS+uuMA1A2UhOfcUYeoqnTW7msLr2RyYAys15pD960hlDfq7QAi8BCAKk0sQ2rjsl0iqMyziohQ==}
/@next/swc-linux-arm64-musl/12.3.1:
resolution: {integrity: sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@ -3244,8 +3253,8 @@ packages:
dev: false
optional: true
/@next/swc-linux-x64-gnu/12.1.6:
resolution: {integrity: sha512-AC7jE4Fxpn0s3ujngClIDTiEM/CQiB2N2vkcyWWn6734AmGT03Duq6RYtPMymFobDdAtZGFZd5nR95WjPzbZAQ==}
/@next/swc-linux-x64-gnu/12.3.1:
resolution: {integrity: sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@ -3253,8 +3262,8 @@ packages:
dev: false
optional: true
/@next/swc-linux-x64-musl/12.1.6:
resolution: {integrity: sha512-c9Vjmi0EVk0Kou2qbrynskVarnFwfYIi+wKufR9Ad7/IKKuP6aEhOdZiIIdKsYWRtK2IWRF3h3YmdnEa2WLUag==}
/@next/swc-linux-x64-musl/12.3.1:
resolution: {integrity: sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@ -3262,8 +3271,8 @@ packages:
dev: false
optional: true
/@next/swc-win32-arm64-msvc/12.1.6:
resolution: {integrity: sha512-3UTOL/5XZSKFelM7qN0it35o3Cegm6LsyuERR3/OoqEExyj3aCk7F025b54/707HTMAnjlvQK3DzLhPu/xxO4g==}
/@next/swc-win32-arm64-msvc/12.3.1:
resolution: {integrity: sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
@ -3271,8 +3280,8 @@ packages:
dev: false
optional: true
/@next/swc-win32-ia32-msvc/12.1.6:
resolution: {integrity: sha512-8ZWoj6nCq6fI1yCzKq6oK0jE6Mxlz4MrEsRyu0TwDztWQWe7rh4XXGLAa2YVPatYcHhMcUL+fQQbqd1MsgaSDA==}
/@next/swc-win32-ia32-msvc/12.3.1:
resolution: {integrity: sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
@ -3280,8 +3289,8 @@ packages:
dev: false
optional: true
/@next/swc-win32-x64-msvc/12.1.6:
resolution: {integrity: sha512-4ZEwiRuZEicXhXqmhw3+de8Z4EpOLQj/gp+D9fFWo6ii6W1kBkNNvvEx4A90ugppu+74pT1lIJnOuz3A9oQeJA==}
/@next/swc-win32-x64-msvc/12.3.1:
resolution: {integrity: sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@ -3613,6 +3622,12 @@ packages:
'@swc/core-win32-x64-msvc': 1.2.210
dev: true
/@swc/helpers/0.4.11:
resolution: {integrity: sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==}
dependencies:
tslib: 2.4.0
dev: false
/@szmarczak/http-timer/1.1.2:
resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==}
engines: {node: '>=6'}
@ -5077,6 +5092,11 @@ packages:
/caniuse-lite/1.0.30001338:
resolution: {integrity: sha512-1gLHWyfVoRDsHieO+CaeYe7jSo/MT7D7lhaXUiwwbuR5BwQxORs0f1tAwUSQr3YbxRXJvxHM/PA5FfPQRnsPeQ==}
dev: true
/caniuse-lite/1.0.30001419:
resolution: {integrity: sha512-aFO1r+g6R7TW+PNQxKzjITwLOyDhVRLjW0LcwS/HCZGUUKTGNp9+IwLC4xyDSZBygVL/mxaFR3HIV6wEKQuSzw==}
dev: false
/capital-case/1.0.4:
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
@ -6148,7 +6168,7 @@ packages:
eslint-plugin-import: 2.26.0_hhyjdrupy4c2vgtpytri6cjwoy
dev: true
/eslint-config-next/12.1.4_e6a2zi6fqdwfehht5cxvkmo3zu:
/eslint-config-next/12.1.4_c2ous3fcmy6f3xlzfnkf2jzbvm:
resolution: {integrity: sha512-Uj0jrVjoQbg9qerxRjSHoOOv3PEzoZxpb8G9LYct25fsflP8xIiUq0l4WEu2KSB5owuLv5hie7wSMqPEsHj+bQ==}
peerDependencies:
eslint: ^7.23.0 || ^8.0.0
@ -6168,7 +6188,7 @@ packages:
eslint-plugin-jsx-a11y: 6.5.1_eslint@8.12.0
eslint-plugin-react: 7.29.1_eslint@8.12.0
eslint-plugin-react-hooks: 4.3.0_eslint@8.12.0
next: 12.1.6_talmm3uuvp6ssixt2qevhfgvue
next: 12.3.1_talmm3uuvp6ssixt2qevhfgvue
typescript: 4.6.4
transitivePeerDependencies:
- eslint-import-resolver-webpack
@ -9670,8 +9690,8 @@ packages:
engines: {node: '>= 0.6'}
dev: false
/next/12.1.6_talmm3uuvp6ssixt2qevhfgvue:
resolution: {integrity: sha512-cebwKxL3/DhNKfg9tPZDQmbRKjueqykHHbgaoG4VBRH3AHQJ2HO0dbKFiS1hPhe1/qgc2d/hFeadsbPicmLD+A==}
/next/12.3.1_talmm3uuvp6ssixt2qevhfgvue:
resolution: {integrity: sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==}
engines: {node: '>=12.22.0'}
hasBin: true
peerDependencies:
@ -9688,25 +9708,28 @@ packages:
sass:
optional: true
dependencies:
'@next/env': 12.1.6
caniuse-lite: 1.0.30001338
postcss: 8.4.5
'@next/env': 12.3.1
'@swc/helpers': 0.4.11
caniuse-lite: 1.0.30001419
postcss: 8.4.14
react: 18.1.0
react-dom: 18.1.0_react@18.1.0
styled-jsx: 5.0.2_vm2wkhzl5f5eyl7hfuywll6uzq
styled-jsx: 5.0.7_vm2wkhzl5f5eyl7hfuywll6uzq
use-sync-external-store: 1.2.0_react@18.1.0
optionalDependencies:
'@next/swc-android-arm-eabi': 12.1.6
'@next/swc-android-arm64': 12.1.6
'@next/swc-darwin-arm64': 12.1.6
'@next/swc-darwin-x64': 12.1.6
'@next/swc-linux-arm-gnueabihf': 12.1.6
'@next/swc-linux-arm64-gnu': 12.1.6
'@next/swc-linux-arm64-musl': 12.1.6
'@next/swc-linux-x64-gnu': 12.1.6
'@next/swc-linux-x64-musl': 12.1.6
'@next/swc-win32-arm64-msvc': 12.1.6
'@next/swc-win32-ia32-msvc': 12.1.6
'@next/swc-win32-x64-msvc': 12.1.6
'@next/swc-android-arm-eabi': 12.3.1
'@next/swc-android-arm64': 12.3.1
'@next/swc-darwin-arm64': 12.3.1
'@next/swc-darwin-x64': 12.3.1
'@next/swc-freebsd-x64': 12.3.1
'@next/swc-linux-arm-gnueabihf': 12.3.1
'@next/swc-linux-arm64-gnu': 12.3.1
'@next/swc-linux-arm64-musl': 12.3.1
'@next/swc-linux-x64-gnu': 12.3.1
'@next/swc-linux-x64-musl': 12.3.1
'@next/swc-win32-arm64-msvc': 12.3.1
'@next/swc-win32-ia32-msvc': 12.3.1
'@next/swc-win32-x64-msvc': 12.3.1
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
@ -10350,8 +10373,8 @@ packages:
source-map-js: 1.0.2
dev: true
/postcss/8.4.5:
resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==}
/postcss/8.4.14:
resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==}
engines: {node: ^10 || ^12 || >=14}
dependencies:
nanoid: 3.3.4
@ -11420,8 +11443,8 @@ packages:
tslib: 2.4.0
dev: false
/styled-jsx/5.0.2_vm2wkhzl5f5eyl7hfuywll6uzq:
resolution: {integrity: sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==}
/styled-jsx/5.0.7_vm2wkhzl5f5eyl7hfuywll6uzq:
resolution: {integrity: sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==}
engines: {node: '>= 12.0.0'}
peerDependencies:
'@babel/core': '*'
@ -12246,6 +12269,14 @@ packages:
tslib: 2.4.0
dev: false
/use-sync-external-store/1.2.0_react@18.1.0:
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies:
react: 18.1.0
dev: false
/util-deprecate/1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}

View file

@ -141,10 +141,14 @@ if [[ "$command" = "uninstall" ]]; then
write_log "Failed to uninstall app ${app}"
exit 1
fi
if ! compose "${app}" down --rmi all --remove-orphans; then
# just stop it if we can't remove the images
if ! compose "${app}" rm --force --stop; then
write_log "Failed to uninstall app ${app}"
exit 1
fi
fi
write_log "Deleting app data for app ${app}..."
if [[ -d "${app_data_dir}" ]]; then
@ -167,9 +171,12 @@ if [[ "$command" = "update" ]]; then
fi
if ! compose "${app}" down --rmi all --remove-orphans; then
write_log "Failed to update app ${app}"
# just stop it if we can't remove the images
if ! compose "${app}" rm --force --stop; then
write_log "Failed to uninstall app ${app}"
exit 1
fi
fi
# Remove app
if [[ -d "${app_dir}" ]]; then
@ -214,4 +221,12 @@ if [[ "$command" = "compose" ]]; then
exit 0
fi
if [[ "$command" = "clean" ]]; then
# Remove all stopped containers and unused images
write_log "Cleaning up..."
docker system prune --all --force
exit 0
fi
exit 1

View file

@ -55,7 +55,7 @@ if [[ "$command" = "update" ]]; then
write_log "Updating ${repo} in ${repo_hash}"
cd "${repo_dir}" || exit
if ! git pull origin master; then
if ! git pull origin "$(git rev-parse --abbrev-ref HEAD)"; then
cd "${ROOT_FOLDER}" || exit
write_log "Failed to update repo"
exit 1

View file

@ -12,7 +12,7 @@ SED_ROOT_FOLDER="$(echo "$ROOT_FOLDER" | sed 's/\//\\\//g')"
NGINX_PORT=80
NGINX_PORT_SSL=443
DOMAIN=tipi.localhost
DNS_IP=9.9.9.9 # Default to Quad9 DNS
DNS_IP="9.9.9.9" # Default to Quad9 DNS
ARCHITECTURE="$(uname -m)"
TZ="UTC"
JWT_SECRET=secret
@ -21,6 +21,18 @@ TIPI_VERSION=$(get_json_field "${ROOT_FOLDER}/package.json" version)
INTERNAL_IP=localhost
storage_path="${ROOT_FOLDER}"
STORAGE_PATH_ESCAPED="$(echo "${storage_path}" | sed 's/\//\\\//g')"
if [[ "$ARCHITECTURE" == "aarch64" ]]; then
ARCHITECTURE="arm64"
elif [[ "$ARCHITECTURE" == "armv7l" ]]; then
ARCHITECTURE="arm"
elif [[ "$ARCHITECTURE" == "x86_64" ]]; then
ARCHITECTURE="amd64"
fi
# If none of the above conditions are met, the architecture is not supported
if [[ "$ARCHITECTURE" != "arm64" ]] && [[ "$ARCHITECTURE" != "arm" ]] && [[ "$ARCHITECTURE" != "amd64" ]]; then
echo "Architecture not supported!"
exit 1
fi
### --------------------------------
### Apps repository configuration

View file

@ -12,7 +12,9 @@ ensure_pwd
ensure_root
clean_logs
# Configure Tipi
### --------------------------------
### Pre-configuration
### --------------------------------
"${ROOT_FOLDER}/scripts/configure.sh"
STATE_FOLDER="${ROOT_FOLDER}/state"
@ -22,12 +24,14 @@ if [[ ! -f "${STATE_FOLDER}/seed" ]]; then
tr </dev/urandom -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1 >"${STATE_FOLDER}/seed"
fi
# Default variables
### --------------------------------
### General variables
### --------------------------------
NGINX_PORT=80
NGINX_PORT_SSL=443
DOMAIN=tipi.localhost
SED_ROOT_FOLDER="$(echo "$ROOT_FOLDER" | sed 's/\//\\\//g')"
DNS_IP=9.9.9.9 # Default to Quad9 DNS
DNS_IP="9.9.9.9" # Default to Quad9 DNS
ARCHITECTURE="$(uname -m)"
TZ="$(timedatectl | grep "Time zone" | awk '{print $3}' | sed 's/\//\\\//g' || Europe\/Berlin)"
apps_repository="https://github.com/meienberger/runtipi-appstore"
@ -61,6 +65,16 @@ INTERNAL_IP="$(ip addr show "${NETWORK_INTERFACE}" | grep "inet " | awk '{print
if [[ "$ARCHITECTURE" == "aarch64" ]]; then
ARCHITECTURE="arm64"
elif [[ "$ARCHITECTURE" == "armv7"* || "$ARCHITECTURE" == "armv8"* ]]; then
ARCHITECTURE="arm"
elif [[ "$ARCHITECTURE" == "x86_64" ]]; then
ARCHITECTURE="amd64"
fi
# If none of the above conditions are met, the architecture is not supported
if [[ "$ARCHITECTURE" != "arm64" ]] && [[ "$ARCHITECTURE" != "arm" ]] && [[ "$ARCHITECTURE" != "amd64" ]]; then
echo "Architecture ${ARCHITECTURE} not supported!"
exit 1
fi
### --------------------------------
@ -129,21 +143,18 @@ if [[ "${NGINX_PORT}" != "80" ]] && [[ "${DOMAIN}" != "tipi.localhost" ]]; then
exit 1
fi
# Run system-info.sh
### --------------------------------
### Watcher and system-info
### --------------------------------
echo "Running system-info.sh..."
"${ROOT_FOLDER}/scripts/system-info.sh"
kill_watcher
"${ROOT_FOLDER}/scripts/watcher.sh" &
# Copy the config sample if it isn't here
if [[ ! -f "${STATE_FOLDER}/apps.json" ]]; then
cp "${ROOT_FOLDER}/templates/config-sample.json" "${STATE_FOLDER}/config.json"
fi
export DOCKER_CLIENT_TIMEOUT=240
export COMPOSE_HTTP_TIMEOUT=240
### --------------------------------
### settings.json overrides
### --------------------------------
echo "Generating config files..."
# Override vars with values from settings.json
if [[ -f "${STATE_FOLDER}/settings.json" ]]; then
@ -216,7 +227,9 @@ done
mv -f "$ENV_FILE" "$ROOT_FOLDER/.env"
## Don't run if config-only
### --------------------------------
### Start the project
### --------------------------------
if [[ ! $ci == "true" ]]; then
if [[ $rc == "true" ]]; then

View file

@ -27,7 +27,7 @@ if [[ "$command" = "update" ]]; then
scripts/stop.sh
git config --global --add safe.directory "${ROOT_FOLDER}"
git pull origin master
git pull origin "$(git rev-parse --abbrev-ref HEAD)"
scripts/start.sh
exit
fi