Merge pull request #147 from meienberger/release/0.4.2

Release/0.4.2
This commit is contained in:
Nicolas Meienberger 2022-07-26 23:20:39 +02:00 committed by GitHub
commit bff6c57daf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 369 additions and 30 deletions

8
.gitignore vendored
View file

@ -1,10 +1,9 @@
.pnpm-debug.log
.env*
data/
github.secrets
node_modules/
app-data/*
data/
data/postgres
traefik/ssl/*
!traefik/ssl/.gitkeep
!app-data/.gitkeep
@ -16,10 +15,13 @@ state/*
media/data/movies/*
media/data/tv/*
media/data/books/*
media/data/books/spoken/*
media/data/books/ebooks/*
!media/data/movies/.gitkeep
!media/data/tv/.gitkeep
!media/data/books/metadata.db
!media/data/books/ebooks/.gitkeep
!media/data/books/spoken/.gitkeep
media/torrents/complete/*
!media/torrents/complete/.gitkeep

View file

@ -3,7 +3,7 @@ FROM alpine:3.16.0 as app
WORKDIR /
# Install docker
RUN apk --no-cache add docker-compose nodejs npm bash
RUN apk --no-cache add docker-compose nodejs npm bash g++ make
RUN npm install node-gyp -g

View file

@ -24,6 +24,7 @@ Check our demo instance : **95.179.210.152** / username: **user@runtipi.com** /
- [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
- [Homarr](https://github.com/ajnart/homarr) - A homepage for your server
@ -38,11 +39,14 @@ Check our demo instance : **95.179.210.152** / username: **user@runtipi.com** /
- [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
- [Overseerr](https://github.com/sct/overseerr) - Request management and media discovery tool for the Plex ecosystem
- [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.
- [Prowlarr](https://github.com/Prowlarr/Prowlarr/) - A torrent/usenet indexer manager/proxy
- [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
- [Sonarr](https://github.com/Sonarr/Sonarr) - TV show manager for Usenet and BitTorrent
- [Syncthing](https://github.com/syncthing/syncthing) - Continuous File Synchronization

View file

@ -0,0 +1,35 @@
{
"name": "Firefly III",
"available": true,
"port": 8115,
"id": "firefly-iii",
"categories": ["finance"],
"description": "",
"short_desc": "Firefly III: a personal finances manager ",
"author": "JC5",
"website": "https://www.firefly-iii.org/",
"source": "https://github.com/firefly-iii/firefly-iii",
"image": "/logos/apps/firefly-iii.jpg",
"form_fields": [
{
"type": "email",
"label": "Your email",
"required": true,
"env_variable": "EMAIL"
},
{
"type": "random",
"min": 32,
"max": 32,
"label": "Random key",
"env_variable": "APP_KEY"
},
{
"type": "random",
"min": 32,
"max": 32,
"label": "Database password",
"env_variable": "MYSQL_PASSWORD"
}
]
}

View file

@ -0,0 +1,59 @@
version: '3.9'
services:
firefly-iii:
image: fireflyiii/core:latest
container_name: firefly-iii
restart: unless-stopped
volumes:
- ${APP_DATA_DIR}/data/uplodad:/var/www/html/storage/upload
ports:
- ${APP_PORT}:8080
depends_on:
- firefly-iii-db
environment:
- APP_ENV=local
- APP_DEBUG=false
- SITE_OWNER=${EMAIL}
- APP_KEY=${APP_KEY}
- TZ=${TZ}
- TRUSTED_PROXIES=**
# Database
- DB_CONNECTION=mysql
- DB_HOST=firefly-iii-db
- DB_PORT=3306
- DB_DATABASE=firefly
- DB_USERNAME=firefly
- DB_PASSWORD=${MYSQL_PASSWORD}
# Cookie settings
- COOKIE_PATH="/"
- COOKIE_DOMAIN=
- COOKIE_SECURE=false
- COOKIE_SAMESITE=lax
- APP_NAME=FireflyIII
- BROADCAST_DRIVER=log
- QUEUE_DRIVER=sync
- CACHE_PREFIX=firefly
- IS_HEROKU=false
- FIREFLY_III_LAYOUT=v1
- APP_URL=http://localhost:${APP_PORT}
networks:
- tipi_main_network
firefly-iii-db:
container_name: firefly-iii-db
image: mariadb
hostname: fireflyiii-db
restart: unless-stopped
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_USER=firefly
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=firefly
volumes:
- ${APP_DATA_DIR}/data/db:/var/lib/mysql
networks:
- tipi_main_network

View file

@ -0,0 +1,26 @@
"Firefly III" is a (self-hosted) manager for your personal finances. It can help you keep track of your expenses and income, so you can spend less and save more. Firefly III supports the use of budgets, categories and tags. Using a bunch of external tools, you can import data. It also has many neat financial reports available.
Firefly III should give you **insight** into and **control** over your finances. Money should be useful, not scary. You should be able to *see* where it is going, to *feel* your expenses and to... wow, I'm going overboard with this aren't I?
But you get the idea: this is your money. These are your expenses. Stop them from controlling you. I built this tool because I started to dislike money. Having money, not having money, paying bills with money, you get the idea. But no more. I want to feel "safe", whatever my balance is. And I hope this tool can help you. I know it helps me.
![Firefly III on iMac](https://raw.githubusercontent.com/firefly-iii/firefly-iii/develop/.github/assets/img/imac-complete.png)
### Purpose
Personal financial management is pretty difficult, and everybody has their own approach to it. Some people make budgets, other people limit their cashflow by throwing away their credit cards, others try to increase their current cashflow. There are tons of ways to save and earn money. Firefly III works on the principle that if you know where your money is going, you can stop it from going there.
By keeping track of your expenses and your income you can budget accordingly and save money. Stop living from paycheck to paycheck but give yourself the financial wiggle room you need.
You can read more about the purpose of Firefly III in the [documentation](https://docs.firefly-iii.org/).
![Firefly III on iPad](https://raw.githubusercontent.com/firefly-iii/firefly-iii/develop/.github/assets/img/ipad-complete.png)
## Need help?
If you need support using Firefly III or the associated tools, come find us!
- [GitHub Discussions for questions and support](https://github.com/firefly-iii/firefly-iii/discussions/)
- [Gitter.im for a good chat and a quick answer](https://gitter.im/firefly-iii/firefly-iii)
- [GitHub Issues for bugs and issues](https://github.com/firefly-iii/firefly-iii/issues)
- [Follow me around for news and updates on Twitter](https://twitter.com/Firefly_iii)

View file

@ -0,0 +1,13 @@
{
"name": "Overseerr",
"available": true,
"port": 8116,
"id": "overseerr",
"categories": ["media", "utilities"],
"description": "Overseerr is a free and open source software application for managing requests for your media library. It integrates with your existing services, such as Sonarr, Radarr, and Plex!",
"short_desc": "Request management and media discovery tool for the Plex ecosystem",
"author": "sct",
"source": "https://github.com/sct/overseerr",
"image": "/logos/apps/overseerr.jpg",
"form_fields": []
}

View file

@ -0,0 +1,16 @@
version: "3"
services:
overseerr:
container_name: overseerr
image: sctx/overseerr:latest
environment:
- TZ=${TZ}
volumes:
- ${APP_DATA_DIR}/data/config:/app/config
ports:
- ${APP_PORT}:5055
restart: unless-stopped
dns:
- ${DNS_IP}
networks:
- tipi_main_network

View file

@ -0,0 +1,14 @@
**Overseerr** is a free and open source software application for managing requests for your media library. It integrates with your existing services, such as **[Sonarr](https://sonarr.tv/)**, **[Radarr](https://radarr.video/)**, and **[Plex](https://www.plex.tv/)**!
## Current Features
- Full Plex integration. Authenticate and manage user access with Plex!
- Easy integration with your existing services. Currently, Overseerr supports Sonarr and Radarr. More to come!
- Plex library scan, to keep track of the titles which are already available.
- Customizable request system, which allows users to request individual seasons or movies in a friendly, easy-to-use interface.
- Incredibly simple request management UI. Don't dig through the app to simply approve recent requests!
- Granular permission system.
- Support for various notification agents.
- Mobile-friendly design, for when you need to approve requests on the go!
With more features on the way! Check out our [issue tracker](https://github.com/sct/overseerr/issues) to see the features which have already been requested.

View file

@ -0,0 +1,13 @@
{
"name": "Portainer",
"port": 9443,
"available": true,
"id": "portainer",
"categories": ["utilities"],
"description": "",
"short_desc": "Making Docker and Kubernetes management easy.",
"author": "portainer.io",
"source": "https://github.com/portainer/portainer",
"image": "/logos/apps/portainer.jpg",
"form_fields": []
}

View file

@ -0,0 +1,14 @@
version: "3.9"
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
ports:
- "${APP_PORT}:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- "${APP_DATA_DIR}/data:/data"
networks:
- tipi_main_network

View file

@ -0,0 +1,6 @@
![Screenshot](https://github.com/portainer/portainer/blob/develop/app/assets/images/portainer-github-banner.png?raw=true)
**Portainer Community Edition** is a lightweight service delivery platform for containerized applications that can be used to manage Docker, Swarm, Kubernetes and ACI environments. It is designed to be as simple to deploy as it is to use. The application allows you to manage all your orchestrator resources (containers, images, volumes, networks and more) through a smart GUI and/or an extensive API.
Portainer consists of a single container that can run on any cluster. It can be deployed as a Linux container or a Windows native container.

13
apps/readarr/config.json Normal file
View file

@ -0,0 +1,13 @@
{
"name": "Readarr",
"available": true,
"port": 8112,
"id": "readarr",
"categories": ["books", "media"],
"description": "",
"short_desc": "Book Manager and Automation (Sonarr for Ebooks)",
"author": "readarr.com",
"source": "https://github.com/Readarr/Readarr",
"image": "/logos/apps/readarr.jpg",
"form_fields": []
}

View file

@ -0,0 +1,20 @@
version: "3.9"
services:
readarr:
image: lscr.io/linuxserver/readarr:develop
container_name: readarr
environment:
- PUID=1000
- PGID=1000
- TZ=${TZ}
dns:
- ${DNS_IP}
volumes:
- /etc/localtime:/etc/localtime:ro
- ${APP_DATA_DIR}/data:/config
- ${ROOT_FOLDER_HOST}/media:/media
ports:
- ${APP_PORT}:8787
restart: unless-stopped
networks:
- tipi_main_network

View file

@ -0,0 +1,22 @@
Readarr is an ebook and audiobook collection manager for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new books from your favorite authors and will grab, sort, and rename them.
Note that only one type of a given book is supported. If you want both an audiobook and ebook of a given book you will need multiple instances.
## Major Features Include
* Can watch for better quality of the ebooks and audiobooks you have and do an automatic upgrade. *e.g. from PDF to AZW3*
* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc.
* Automatically detects new books
* Can scan your existing library and download any missing books
* Automatic failed download handling will try another release if one fails
* Manual search so you can pick any release or to see why a release was not downloaded automatically
* Advanced customization for profiles, such that Readarr will always download the copy you want
* Fully configurable book renaming
* SABnzbd, NZBGet, QBittorrent, Deluge, rTorrent, Transmission, uTorrent, and other download clients are supported and integrated
* Full integration with Calibre (add to library, conversion) (Requires Calibre Content Server)
* And a beautiful UI
## Support
[![Wiki](https://img.shields.io/badge/servarr-wiki-181717.svg?maxAge=60)](https://wiki.servarr.com/readarr)
[![Discord](https://img.shields.io/badge/discord-chat-7289DA.svg?maxAge=60)](https://readarr.com/discord)
[![Reddit](https://img.shields.io/badge/reddit-discussion-FF4500.svg?maxAge=60)](https://www.reddit.com/r/readarr)

View file

@ -29,7 +29,7 @@ services:
POSTGRES_USER: tipi
POSTGRES_DB: tipi
healthcheck:
test: [ "CMD-SHELL", "pg_isready -d tipi -U tipi" ]
test: ["CMD-SHELL", "pg_isready -d tipi -U tipi"]
interval: 5s
timeout: 10s
retries: 120
@ -59,6 +59,9 @@ services:
POSTGRES_USERNAME: tipi
POSTGRES_DBNAME: tipi
POSTGRES_HOST: tipi-db
NODE_ENV: production
dns:
- ${DNS_IP}
networks:
- tipi_main_network
@ -71,7 +74,8 @@ services:
networks:
- tipi_main_network
environment:
- INTERNAL_IP=${INTERNAL_IP}
INTERNAL_IP: ${INTERNAL_IP}
NODE_ENV: production
labels:
traefik.enable: true
traefik.http.routers.dashboard.rule: PathPrefix("/") # Host(`tipi.local`) &&

View file

@ -29,7 +29,7 @@ services:
POSTGRES_USER: tipi
POSTGRES_DB: tipi
healthcheck:
test: [ "CMD-SHELL", "pg_isready -d tipi -U tipi" ]
test: ["CMD-SHELL", "pg_isready -d tipi -U tipi"]
interval: 5s
timeout: 10s
retries: 120
@ -60,6 +60,9 @@ services:
POSTGRES_USERNAME: tipi
POSTGRES_DBNAME: tipi
POSTGRES_HOST: tipi-db
NODE_ENV: production
dns:
- ${DNS_IP}
networks:
- tipi_main_network
@ -73,7 +76,8 @@ services:
networks:
- tipi_main_network
environment:
- INTERNAL_IP=${INTERNAL_IP}
INTERNAL_IP: ${INTERNAL_IP}
NODE_ENV: production
labels:
traefik.enable: true
traefik.http.routers.dashboard.rule: PathPrefix("/") # Host(`tipi.local`) &&

View file

View file

View file

@ -1,6 +1,6 @@
{
"name": "runtipi",
"version": "0.4.1",
"version": "0.4.2",
"description": "A homeserver for everyone",
"scripts": {
"test": "jest",

View file

@ -1,6 +1,6 @@
{
"name": "dashboard",
"version": "0.4.1",
"version": "0.4.2",
"private": true,
"scripts": {
"test": "jest --colors",

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View file

@ -13,4 +13,5 @@ export const APP_CATEGORIES = [
{ name: 'Books', id: AppCategoriesEnum.Books, icon: 'FaBook' },
{ name: 'Data', id: AppCategoriesEnum.Data, icon: 'FaDatabase' },
{ name: 'Music', id: AppCategoriesEnum.Music, icon: 'FaMusic' },
{ name: 'Finance', id: AppCategoriesEnum.Finance, icon: 'FaMoneyBillAlt' },
];

View file

@ -37,6 +37,7 @@ export enum AppCategoriesEnum {
Data = 'DATA',
Development = 'DEVELOPMENT',
Featured = 'FEATURED',
Finance = 'FINANCE',
Media = 'MEDIA',
Music = 'MUSIC',
Network = 'NETWORK',

View file

@ -38,4 +38,5 @@ export const colorSchemeForCategory: Record<AppCategoriesEnum, string> = {
[AppCategoriesEnum.Data]: 'red',
[AppCategoriesEnum.Books]: 'blue',
[AppCategoriesEnum.Music]: 'green',
[AppCategoriesEnum.Finance]: 'orange',
};

View file

@ -11,6 +11,9 @@ interface IProps {
initalValues?: Record<string, string>;
}
const hiddenTypes = ['random'];
const typeFilter = (field: FormField) => !hiddenTypes.includes(field.type);
const InstallForm: React.FC<IProps> = ({ formFields, onSubmit, initalValues }) => {
const renderField = (field: FormField) => {
return (
@ -30,7 +33,7 @@ const InstallForm: React.FC<IProps> = ({ formFields, onSubmit, initalValues }) =
validate={(values) => validateAppConfig(values, formFields)}
render={({ handleSubmit, validating, submitting }) => (
<form className="flex flex-col" onSubmit={handleSubmit}>
{formFields.map(renderField)}
{formFields.filter(typeFilter).map(renderField)}
<Button isLoading={validating || submitting} className="self-end mb-2" colorScheme="green" type="submit">
{initalValues ? 'Update' : 'Install'}
</Button>

View file

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

View file

@ -20,6 +20,8 @@ if (process.env.NODE_ENV !== 'production') {
dotenv.config({ path: '.env' });
}
console.log('Production => ', process.env.NODE_ENV === 'production');
const {
LOGS_FOLDER = 'logs',
LOGS_APP = 'app.log',

View file

@ -0,0 +1,38 @@
import datasource from '../../config/datasource';
import App from '../../modules/apps/app.entity';
import User from '../../modules/auth/user.entity';
import Update from '../../modules/system/update.entity';
const recover = async () => {
console.log('Recovering broken database');
const apps = await App.find();
const users = await User.find();
const updated = await Update.find();
// drop database
await datasource.dropDatabase();
console.log('running migrations');
await datasource.runMigrations();
// create users
for (const user of users) {
await User.create(user).save();
}
// create apps
for (const app of apps) {
await App.create(app).save();
}
// create updates
for (const update of updated) {
await Update.create(update).save();
}
console.log('Users recovered', users.length);
console.log('Apps recovered', apps.length);
console.log('Database recovered');
};
export default recover;

View file

@ -1,6 +1,7 @@
import portUsed from 'tcp-port-used';
import { fileExists, readdirSync, readFile, readJsonFile, runScript, writeFile } from '../fs/fs.helpers';
import InternalIp from 'internal-ip';
import crypto from 'crypto';
import config from '../../config';
import { AppInfo } from './apps.types';
@ -84,17 +85,33 @@ export const ensureAppState = (appName: string, installed: boolean) => {
writeFile('/state/apps.json', JSON.stringify(state));
};
const getEntropy = (name: string, length: number) => {
const hash = crypto.createHash('sha256');
hash.update(name);
return hash.digest('hex').substring(0, length);
};
export const generateEnvFile = (appName: string, form: Record<string, string>) => {
const configFile: AppInfo = readJsonFile(`/apps/${appName}/config.json`);
const baseEnvFile = readFile('/.env').toString();
let envFile = `${baseEnvFile}\nAPP_PORT=${configFile.port}\n`;
const envMap = getEnvMap(appName);
configFile.form_fields?.forEach((field) => {
const formValue = form[field.env_variable];
const envVar = field.env_variable;
if (formValue) {
const envVar = field.env_variable;
envFile += `${envVar}=${formValue}\n`;
} else if (field.type === 'random') {
if (envMap.has(envVar)) {
envFile += `${envVar}=${envMap.get(envVar)}\n`;
} else {
const length = field.min || 32;
const randomString = getEntropy(field.env_variable, length);
envFile += `${envVar}=${randomString}\n`;
}
} else if (field.required) {
throw new Error(`Variable ${field.env_variable} is required`);
}

View file

@ -14,6 +14,7 @@ export enum AppCategoriesEnum {
BOOKS = 'books',
DATA = 'data',
MUSIC = 'music',
FINANCE = 'finance',
}
export enum FieldTypes {
@ -25,6 +26,7 @@ export enum FieldTypes {
ip = 'ip',
fqdnip = 'fqdnip',
url = 'url',
random = 'random',
}
export enum AppStatusEnum {

View file

@ -14,21 +14,24 @@ import cors from 'cors';
import datasource from './config/datasource';
import appsService from './modules/apps/apps.service';
import { runUpdates } from './core/updates/run';
import recover from './core/updates/recover-migrations';
const corsOptions = {
credentials: true,
origin: function (origin: any, callback: any) {
// disallow requests with no origin
if (!origin) return callback(new Error('Not allowed by CORS'), false);
let corsOptions = __prod__
? {
credentials: true,
origin: function (origin: any, callback: any) {
// disallow requests with no origin
if (!origin) return callback(new Error('Not allowed by CORS'), false);
if (config.CLIENT_URLS.includes(origin)) {
return callback(null, true);
if (config.CLIENT_URLS.includes(origin)) {
return callback(null, true);
}
const message = "The CORS policy for this origin doesn't allow access from the particular origin.";
return callback(new Error(message), false);
},
}
const message = "The CORS policy for this origin doesn't allow access from the particular origin.";
return callback(new Error(message), false);
},
};
: {};
const main = async () => {
try {
@ -40,10 +43,6 @@ const main = async () => {
await datasource.initialize();
if (__prod__) {
await datasource.runMigrations();
}
const schema = await createSchema();
const httpServer = createServer(app);
const plugins = [ApolloLogs];
@ -61,13 +60,22 @@ const main = async () => {
await apolloServer.start();
apolloServer.applyMiddleware({ app, cors: corsOptions });
if (__prod__) {
try {
await datasource.runMigrations();
} catch (e) {
logger.error(e);
await recover();
}
}
// Run migrations
await runUpdates();
httpServer.listen(port, () => {
// Start apps
appsService.startAllApps();
logger.info(`Server running on port ${port}`);
console.info(`Server running on port ${port} 🚀 Production => ${__prod__}`);
});
} catch (error) {
console.log(error);

1
scripts/unsafe-cleanup.sh Normal file → Executable file
View file

@ -22,6 +22,7 @@ echo y | docker image prune -a
# Remove everything in app-data folder
rm -rf "${ROOT_FOLDER}/app-data"
rm -rf "${ROOT_FOLDER}/data/postgres"
mkdir -p "${ROOT_FOLDER}/app-data"
# Put {"installed":""} in state/apps.json