Skip to content

Commit

Permalink
#11 self-hosting docs
Browse files Browse the repository at this point in the history
  • Loading branch information
damoeb committed May 21, 2023
1 parent e144ffe commit 9ab3b08
Show file tree
Hide file tree
Showing 21 changed files with 184 additions and 139 deletions.
37 changes: 24 additions & 13 deletions .env
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
rootEmail=admin@localhost
rootSecretKey=65a84cf8f10de58411fada48ddba93158983daae
APP_ROOT_EMAIL=admin@localhost
APP_ROOT_SECRET_KEY=password

jwtSecret=60ae393744191ee58869f700c1d27647b0b64d42
apiGatewayUrl=http://localhost:8080
actuatorPassword=password
# sso|mail|root
APP_AUTHENTICATION=root
APP_JWT_SECRET=60ae393744191ee58869f700c1d27647b0b64d42
APP_API_GATEWAY_URL=http://localhost:8080
APP_HOST_URL=http://localhost:4200
APP_ACTUATOR_PASSWORD=password
APP_TIMEZONE=Europe/Berlin
APP_LOG_LEVEL=error

# MAIL
APP_MAIL_SENDER=
APP_MAIL_HOST=
APP_MAIL_PORT=
APP_MAIL_USERNAME=
APP_MAIL_PASSWORD=

# database
sqlUser=postgres
sqlPassword=admin
sqlUrl=jdbc:postgresql://localhost:5432/
databaseName=feedless
POSTGRES_USER=postgres
POSTGRES_PASSWORD=admin
POSTGRES_DB=feedless

# sso provider
googleClientId=343423943511-t83rkoi6ul369b2e2p2it8dt5554i9cu.apps.googleusercontent.com
googleClientSecret=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
SSO_GOOGLE_CLIENT_ID=
SSO_GOOGLE_CLIENT_SECRET=

githubClientId=Iv1.3fc36e6644b030c3
githubClientSecret=b49d33465c75bcbc78fa7e3b313266f8c41f4e63
SSO_GITHUB_CLIENT_ID=
SSO_GITHUB_CLIENT_SECRET=
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# feedless

`feedless` is a web app to create RSS+ feeds of most HTMLs and to manage any ATOM/RSS or JSON feed. These feed can be manipulated and remixed.
You may [Self-host](./docs/hosting.md) or join [feedless.org](https://feedless.org) to create and share feeds.
You may [Self-host](./docs/self-hosting.md) or join [feedless.org](https://feedless.org) to create and share feeds.


[![Watch the video](docs/screenshot.png)](https://www.youtube.com/watch?v=PolMYwBVmzc)
Expand All @@ -15,7 +15,7 @@ You may [Self-host](./docs/hosting.md) or join [feedless.org](https://feedless.o
- [JavaScript Support](./packages/agent/README.md) of JavaScript-based websites
- Inline Images for archive/privacy purposes
- Extendable using [Plugins](docs/plugins.md)
- Simple [Self-hosting](./docs/hosting.md)
- Simple [Self-hosting](./docs/self-hosting.md)
- [Third-party migration](./docs/third-party-migration.md)

# Client Modules
Expand All @@ -27,7 +27,7 @@ You may [Self-host](./docs/hosting.md) or join [feedless.org](https://feedless.o
- [agent](./packages/agent/README.md) Puppeteer wrapper ([nestjs](https://nestjs.com/))

# Getting Started
See [Self-hosting](./docs/hosting.md) or [development](./docs/development.md)
See [Self-hosting](./docs/self-hosting.md) or [development](./docs/development.md)

## Changelog
See [changelog](changelog.md)
Expand Down
36 changes: 10 additions & 26 deletions docker-compose.minimal.yml → docker-compose.selfhosting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ services:
container_name: postgres
restart: unless-stopped
environment:
- POSTGRES_DB=${databaseName}
- POSTGRES_USER=${sqlUser}
- POSTGRES_PASSWORD=${sqlPassword}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
expose:
- 5432
ports:
Expand All @@ -28,8 +28,8 @@ services:
- seccomp=./chrome.json
restart: unless-stopped
environment:
- EMAIL=${rootEmail}
- SECRET_KEY=${rootSecretKey}
- EMAIL=${APP_ROOT_EMAIL}
- SECRET_KEY=${APP_ROOT_SECRET_KEY}
- HOST=feedless-core:8080
- SECURE=false
ports:
Expand All @@ -52,29 +52,13 @@ services:
- postgres
ports:
- "8080:8080"
env_file:
- .env
environment:
- sqlUser=${sqlUser}
- sqlPassword=${sqlPassword}
- DATABASE_URL=jdbc:postgresql://postgres:5432/${databaseName}
- invidiousHost=invidious
- APP_API_GATEWAY_URL=${apiGatewayUrl}
- spring_profiles_active=authAllowRoot,database
- APP_TIMEZONE=Europe/Berlin
- APP_WHITESLISTED_HOSTS=feedless-core
- DATABASE_URL=jdbc:postgresql://postgres:5432/${POSTGRES_DB}
- APP_ACTIVE_PROFILES=database
- APP_WHITELISTED_HOSTS=feedless-core
- AUTH_TOKEN_ANONYMOUS_VALIDFORDAYS=3
- LOG_LEVEL=error
- APP_JWT_SECRET=${jwtSecret}
- APP_NITTER_HOST=${nitterHost}
- APP_APP_HOST=${appHost}
- APP_ACTUATOR_PASSWORD=${actuatorPassword}
- ROOT_EMAIL=${rootEmail}
- ROOT_SECRET_KEY=${rootSecretKey}
# https://console.cloud.google.com/apis/credentials
- GOOGLE_CLIENT_ID=${googleClientId}
- GOOGLE_CLIENT_SECRET=${googleClientSecret}
- GITHUB_CLIENT_ID=${githubClientId}
- GITHUB_CLIENT_SECRET=${githubClientSecret}
- DNS_TEST_URL=br.de
networks:
- postgres

Expand Down
38 changes: 11 additions & 27 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ services:
container_name: postgres
restart: unless-stopped
environment:
- POSTGRES_DB=${databaseName}
- POSTGRES_USER=${sqlUser}
- POSTGRES_PASSWORD=${sqlPassword}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
expose:
- 5432
ports:
Expand All @@ -91,8 +91,8 @@ services:
- seccomp=./chrome.json
restart: unless-stopped
environment:
- EMAIL=${rootEmail}
- SECRET_KEY=${rootSecretKey}
- EMAIL=${APP_ROOT_EMAIL}
- SECRET_KEY=${APP_ROOT_SECRET_KEY}
- HOST=feedless-core:8080
- SECURE=false
ports:
Expand All @@ -119,29 +119,13 @@ services:
- postgres
ports:
- "8080:8080"
env_file:
- .env
environment:
- sqlUser=${sqlUser}
- sqlPassword=${sqlPassword}
- DATABASE_URL=jdbc:postgresql://postgres:5432/${databaseName}
- invidiousHost=invidious
- APP_API_GATEWAY_URL=${apiGatewayUrl}
- spring_profiles_active=sso,database
- APP_TIMEZONE=Europe/Berlin
- APP_WHITESLISTED_HOSTS=feedless-core
- DATABASE_URL=jdbc:postgresql://postgres:5432/${POSTGRES_DB}
- APP_ACTIVE_PROFILES=database
- APP_WHITELISTED_HOSTS=feedless-core
- AUTH_TOKEN_ANONYMOUS_VALIDFORDAYS=3
- LOG_LEVEL=info
- APP_JWT_SECRET=${jwtSecret}
- APP_NITTER_HOST=${nitterHost}
- APP_APP_HOST=${appHost}
- APP_ACTUATOR_PASSWORD=${actuatorPassword}
- ROOT_EMAIL=${rootEmail}
- ROOT_SECRET_KEY=${rootSecretKey}
# https://console.cloud.google.com/apis/credentials
- GOOGLE_CLIENT_ID=${googleClientId}
- GOOGLE_CLIENT_SECRET=${googleClientSecret}
- GITHUB_CLIENT_ID=${githubClientId}
- GITHUB_CLIENT_SECRET=${githubClientSecret}
- DNS_TEST_URL=br.de
networks:
- postgres
- monitoring
Expand Down Expand Up @@ -174,7 +158,7 @@ services:
prometheus:
image: prom/prometheus
environment:
- APP_ACTUATOR_PASSWORD=${actuatorPassword}
- APP_ACTUATOR_PASSWORD=${APP_ACTUATOR_PASSWORD}
volumes:
- ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
Expand Down
22 changes: 22 additions & 0 deletions docs/authentication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Authentication Options

By customizing the flag `APP_AUTHENTICATION` you can pick your authentication strategy that suits you best.

## Single Tenant
### Root Login
`APP_AUTHENTICATION=root` will enable the single tenant authentication. You can login in the UI using `$APP_ROOT_EMAIL` and `$APP_ROOT_SECRET_KEY`.

## Multi Tenant
### Magic Link via email (Multi Tenant)
Magic Auth Links is the most decoupled authentication strategy.

`APP_AUTHENTICATION=mail` will activate a two-phased login process using magic links via email.
In order to send emails you need to configure an SMTP server by filling out all `APP_MAIL_*` fields.

This feature is not yet fully implemented. It would need some kind of registration for new users (invitation links or plain signup). Create a ticket if
you think this is useful.

### Single Sign On (Multi Tenant)
SSO is the strategy used in the `feedless` prod deployment, cause it is the most seamless.
By setting `APP_AUTHENTICATION=sso` authentication is run through the defined SSO providers. If the oauth reply is successful, `feedless` will
create its own token for internal authentication.
24 changes: 0 additions & 24 deletions docs/hosting.md

This file was deleted.

45 changes: 45 additions & 0 deletions docs/self-hosting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Self-Hosting feedless

Simplest `feedless` setup is using [docker-compose](https://docs.docker.com/compose/install/linux/).
Configuration is achived by envoronment flags defined in `.env`.

## Preparation
* Download the respective files from the repository.
```shell
wget https://raw.githubusercontent.com/damoeb/feedless/master/.env \
https://raw.githubusercontent.com/damoeb/feedless/master/docker-compose.selfhosting.yml
```
* Customize the `.env` file

## Single Tenant (default)
The default authentication strategy is `root` which is single tenant. You can log in using `$APP_ROOT_EMAIL` and `$APP_ROOT_SECRET_KEY`.
Changing these value require a restart or `core`.

## Multi Tenant
For multi tenant can be enabled by picking a different [authentication strategy](./authentication.md) than root login.

## Start Containers
* Start the containers
```shell
docker-compose -f docker-compose.selfhosting.yml up -d
```

Validate the authentication strategy in the logs (switch `APP_LOG_LEVEL=info`)
```shell
feedless-core_1 | 14:59:56.181 [main] INFO PropertyService - property authentication = authRoot
```

Wait until you see the feedless banner
```shell
feedless-core_1 | . .
feedless-core_1 | ,- | |
feedless-core_1 | | ,-. ,-. ,-| | ,-. ,-. ,-.
feedless-core_1 | |- |-' |-' | | | |-' `-. `-.
feedless-core_1 | | `-' `-' `-' ' `-' `-' `-'
feedless-core_1 | -'
feedless-core_1 |
feedless-core_1 | feedless:core v0.1.0-e144ffe https://github.com/damoeb/feedless
```
and open UI in browser `http://localhost:4200`
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,9 @@
<ion-button routerLink="/notifications" *ngIf="authorization?.loggedIn">
<ion-icon name="notifications-outline"></ion-icon>
</ion-button>
<ion-button routerLink="/plans" *ngIf="!authorization?.loggedIn">
Plans
</ion-button>
<!-- <ion-button> Github </ion-button>-->
<!-- <ion-button> Status </ion-button>-->
<!-- <ion-button routerLink="/plans" *ngIf="!authorization?.loggedIn">-->
<!-- Plans-->
<!-- </ion-button>-->
<ion-button
routerLink="/login"
color="primary"
Expand Down
12 changes: 6 additions & 6 deletions packages/server-core/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ FROM amazoncorretto:17-alpine-jdk
ARG workdir=/usr/feedless
WORKDIR $workdir

ARG CORE_VERSION
ARG GIT_HASH
ENV spring_profiles_active="prod" \
LOG_LEVEL="error" \
CORE_VERSION=$CORE_VERSION \
GIT_HASH=$GIT_HASH
ARG APP_CORE_VERSION
ARG APP_GIT_HASH
ENV APP_ACTIVE_PROFILES="prod" \
APP_LOG_LEVEL="error" \
APP_CORE_VERSION=$APP_CORE_VERSION \
APP_GIT_HASH=$APP_GIT_HASH
EXPOSE 8080
RUN addgroup -g 1000 java && \
adduser -u 1000 -G java -s /bin/sh -D java
Expand Down
4 changes: 2 additions & 2 deletions packages/server-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ val dockerBuild = tasks.register("buildDockerImage", Exec::class) {
// environment("DOCKER_BUILDKIT", "0") // buildx has DNS issues
commandLine(
"docker", "build",
"--build-arg", "CORE_VERSION=$majorMinorPatch",
"--build-arg", "GIT_HASH=$gitHash",
"--build-arg", "APP_CORE_VERSION=$majorMinorPatch",
"--build-arg", "APP_GIT_HASH=$gitHash",
"--platform=linux/amd64",
// "--platform=linux/arm64v8",
"-t", "$imageName-$majorMinorPatch",
Expand Down
2 changes: 1 addition & 1 deletion packages/server-core/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ java -XX:+UseContainerSupport \
-XX:+UnlockExperimentalVMOptions \
-XX:HeapDumpPath=/usr/feedless/java_error_in_feedless_.hprof \
-Duser.timezone=${APP_TIMEZONE} \
-Dspring.profiles.active=prod,${spring_profiles_active} \
-Dspring.profiles.active=prod,${APP_AUTHENTICATION},${APP_ACTIVE_PROFILES} \
-XX:+HeapDumpOnOutOfMemoryError \
-Dfile.encoding=UTF-8 \
-jar app.jar
10 changes: 8 additions & 2 deletions packages/server-core/pre-boot.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
#!/usr/bin/env sh

echo "Verifying DNS resolution using $DNS_TEST_URL"
nslookup $DNS_TEST_URL | grep $DNS_TEST_URL
if test -z "$DNS_TEST_URL"
then
echo "Skipping DNS check"
else
echo "Verifying DNS resolution using $DNS_TEST_URL"
nslookup $DNS_TEST_URL | grep $DNS_TEST_URL
fi

Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ class AppInitListener : ApplicationListener<ApplicationReadyEvent> {

private val log = LoggerFactory.getLogger(AppInitListener::class.simpleName)

@Value("\${CORE_VERSION}")
@Value("\${APP_CORE_VERSION}")
lateinit var version: String

@Value("\${OTHER_VERSIONS}")
lateinit var otherVersion: Optional<String>

@Value("\${GIT_HASH}")
@Value("\${APP_GIT_HASH}")
lateinit var hash: String

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package org.migor.feedless
object AppProfiles {
const val dev = "dev"
const val authSSO = "sso"
const val authMail = "authMail"
const val authMail = "mail"
const val authRoot = "authRoot"
const val database = "database"
const val webGraph = "webgraph"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy

@Configuration
@EnableAspectJAutoProxy

@SpringBootApplication(exclude = [
ReactiveElasticsearchRepositoriesAutoConfiguration::class,
ElasticsearchRepositoriesAutoConfiguration::class,
Expand Down
Loading

0 comments on commit 9ab3b08

Please sign in to comment.