diff --git a/README.md b/README.md index 957462fc..5ebb969d 100644 --- a/README.md +++ b/README.md @@ -14,15 +14,14 @@ A link aggregator / reddit clone for the fediverse. [Lemmy Dev instance](https://dev.lemmy.ml) *for testing purposes only* This is a **very early beta version**, and a lot of features are currently broken or in active development, such as federation. - + Front Page|Post ---|--- ![main screen](https://i.imgur.com/y64BtXC.png)|![chat screen](https://i.imgur.com/vsOr87q.png) - ## Features - Open source, [AGPL License](/LICENSE). - Self hostable, easy to deploy. - - Comes with [docker](#docker). + - Comes with [Docker](#docker), [Kubernetes](#kubernetes). - Live-updating Comment threads. - Full vote scores `(+/-)` like old reddit. - Moderation abilities. @@ -34,7 +33,6 @@ Front Page|Post - High performance. - Server is written in rust. - Front end is `~80kB` gzipped. - ## About [Lemmy](https://github.com/dessalines/lemmy) is similar to sites like [Reddit](https://reddit.com), [Lobste.rs](https://lobste.rs), [Raddle](https://raddle.me), or [Hacker News](https://news.ycombinator.com/): you subscribe to forums you're interested in, post links and discussions, then vote, and comment on them. Behind the scenes, it is very different; anyone can easily run a server, and all these servers are federated (think email), and connected to the same universe, called the [Fediverse](https://en.wikipedia.org/wiki/Fediverse). @@ -51,16 +49,42 @@ Each lemmy server can set its own moderation policy; appointing site-wide admins - The [furry rodents](http://sunchild.fpwc.org/lemming-the-little-giant-of-the-north/). Made with [Rust](https://www.rust-lang.org), [Actix](https://actix.rs/), [Inferno](https://www.infernojs.org), [Typescript](https://www.typescriptlang.org/) and [Diesel](http://diesel.rs/). - ## Install ### Docker Make sure you have both docker and docker-compose installed. + ``` git clone https://github.com/dessalines/lemmy cd lemmy ./docker_update.sh # This pulls the newest version, builds and runs it ``` + and goto http://localhost:8536 +### Kubernetes +#### Requirements +- Local or remote Kubernetes cluster, i.e. [`minikube`](https://kubernetes.io/docs/tasks/tools/install-minikube/) +- [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/) +- [`skaffold`](https://skaffold.dev/) +#### Production +```bash +# Deploy the Traefik Ingress +kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-rbac.yaml +kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-ds.yaml +# Replace ${IP} with your Ingress' IP +echo "${IP} dev.lemmy.local" >> /etc/hosts +``` + +```bash +skaffold run -p lemmy--prod +``` + +Now go to http://dev.lemmy.local. +#### Development +```bash +skaffold dev -p lemmy--dev +``` + +Now go to http://localhost:4444. It automatically proxies to localhost, both if the cluster is local or remote; it also hot-reloads the UI and automatically recompiles and restarts the server. ### Local Development #### Requirements - [Rust](https://www.rust-lang.org/) @@ -80,20 +104,17 @@ cd lemmy # cd ui && yarn start # cd server && cargo watch -x run ``` -and goto http://localhost:8536 +and goto http://localhost:8536 ## Documentation - [ActivityPub API.md](docs/API.md) - [Goals](docs/goals.md) - [Ranking Algorithm](docs/ranking.md) - ## Support Lemmy is free, open-source software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project. - [Support on Patreon](https://www.patreon.com/dessalines). - [Sponsor List](https://dev.lemmy.ml/#/sponsors). - bitcoin: `bc1queu73nwuheqtsp65nyh5hf4jr533r8rr5nsj75` - ethereum: `0x400c96c96acbC6E7B3B43B1dc1BB446540a88A01` - ## Credits - Icons made by [Freepik](https://www.freepik.com/) licensed by [CC 3.0](http://creativecommons.org/licenses/by/3.0/) diff --git a/server/Dockerfile.dev b/server/Dockerfile.dev new file mode 100644 index 00000000..203dd742 --- /dev/null +++ b/server/Dockerfile.dev @@ -0,0 +1,28 @@ +# Setup env +FROM rust:1.33 AS build +RUN USER=root cargo new --bin /opt/lemmy/server--dev +WORKDIR /opt/lemmy/server--dev +# Enable deps caching +RUN mkdir -p src/bin +RUN echo 'fn main() { println!("Dummy") }' >src/bin/main.rs +# Install deps +COPY Cargo.toml . +COPY Cargo.lock . +RUN cargo build --release +RUN rm src/bin/main.rs +# Add app +COPY src/ src/ +COPY migrations/ migrations/ +RUN rm target/release/deps/lemmy* +RUN cargo build --release + +# Setup env (no Alpine because Rust requires glibc) +FROM ubuntu:18.04 +RUN apt update +RUN apt install postgresql-client -y +# Create empty directory where the frontend would normally be +RUN mkdir -p /opt/lemmy/ui--dev/dist +# Add app +COPY --from=build /opt/lemmy/server--dev/target/release/lemmy . +# Run app +CMD ["./lemmy"] diff --git a/server/Dockerfile.prod b/server/Dockerfile.prod new file mode 100644 index 00000000..b375e478 --- /dev/null +++ b/server/Dockerfile.prod @@ -0,0 +1,28 @@ +# Setup env +FROM rust:1.33 AS build +RUN USER=root cargo new --bin /opt/lemmy/server--prod +WORKDIR /opt/lemmy/server--prod +# Enable deps caching +RUN mkdir -p src/bin +RUN echo 'fn main() { println!("Dummy") }' >src/bin/main.rs +# Install deps +COPY Cargo.toml . +COPY Cargo.lock . +RUN cargo build --release +RUN rm src/bin/main.rs +# Add app +COPY src/ src/ +COPY migrations/ migrations/ +RUN rm target/release/deps/lemmy* +RUN cargo build --release + +# Setup env (no Alpine because Rust requires glibc) +FROM ubuntu:18.04 +RUN apt update +RUN apt install postgresql-client -y +# Create empty directory where the frontend would normally be +RUN mkdir -p /opt/lemmy/ui--prod/dist +# Add app +COPY --from=build /opt/lemmy/server--prod/target/release/lemmy . +# Run app +CMD ["./lemmy"] diff --git a/server/stack.dev.yaml b/server/stack.dev.yaml new file mode 100644 index 00000000..7c6905b3 --- /dev/null +++ b/server/stack.dev.yaml @@ -0,0 +1,111 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres +data: + POSTGRES_PASSWORD: rrr + POSTGRES_USER: rrr + POSTGRES_DB: rrr + PGDATA: /var/lib/postgresql/data/pgdata + DATABASE_URL: postgres://rrr:rrr@postgres:5432/rrr +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: postgres +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres +spec: + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:11.2-alpine + resources: + limits: + memory: 256Mi + cpu: 512m + ports: + - containerPort: 5432 + envFrom: + - configMapRef: + name: postgres + volumeMounts: + - name: postgres + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres + persistentVolumeClaim: + claimName: postgres +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres +spec: + selector: + app: postgres + ports: + - port: 5432 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: lemmy-server--dev +data: + LEMMY_FRONT_END_DIR: /opt/lemmy/ui--dev/dist # not actually used here, polyfill for monolith +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lemmy-server--dev +spec: + selector: + matchLabels: + app: lemmy-server--dev + template: + metadata: + labels: + app: lemmy-server--dev + spec: + containers: + - name: lemmy-server--dev + image: registry.gitlab.com/pojntfx/lemmy/server.dev + envFrom: + - configMapRef: + name: postgres + - configMapRef: + name: lemmy-server--dev + resources: + limits: + memory: 512Mi + cpu: 512m + ports: + - containerPort: 8536 +--- +apiVersion: v1 +kind: Service +metadata: + name: lemmy-server--dev +spec: + type: NodePort + selector: + app: lemmy-server--dev + ports: + - port: 8536 + nodePort: 30001 diff --git a/server/stack.prod.yaml b/server/stack.prod.yaml new file mode 100644 index 00000000..d221de16 --- /dev/null +++ b/server/stack.prod.yaml @@ -0,0 +1,110 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres +data: + POSTGRES_PASSWORD: rrr + POSTGRES_USER: rrr + POSTGRES_DB: rrr + PGDATA: /var/lib/postgresql/data/pgdata + DATABASE_URL: postgres://rrr:rrr@postgres:5432/rrr +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: postgres +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres +spec: + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:11.2-alpine + resources: + limits: + memory: 256Mi + cpu: 512m + ports: + - containerPort: 5432 + envFrom: + - configMapRef: + name: postgres + volumeMounts: + - name: postgres + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres + persistentVolumeClaim: + claimName: postgres +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres +spec: + selector: + app: postgres + ports: + - port: 5432 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: lemmy-server--prod +data: + LEMMY_FRONT_END_DIR: /opt/lemmy/ui--prod/dist # not actually used here, polyfill for monolith +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lemmy-server--prod +spec: + selector: + matchLabels: + app: lemmy-server--prod + template: + metadata: + labels: + app: lemmy-server--prod + spec: + containers: + - name: lemmy-server--prod + image: registry.gitlab.com/pojntfx/lemmy/server.prod + envFrom: + - configMapRef: + name: postgres + - configMapRef: + name: lemmy-server--prod + resources: + limits: + memory: 512Mi + cpu: 512m + ports: + - containerPort: 8536 +--- +apiVersion: v1 +kind: Service +metadata: + name: lemmy-server--prod +spec: + selector: + app: lemmy-server--prod + ports: + - port: 8536 + targetPort: 8536 diff --git a/skaffold.yaml b/skaffold.yaml new file mode 100644 index 00000000..9aeaa585 --- /dev/null +++ b/skaffold.yaml @@ -0,0 +1,37 @@ +apiVersion: skaffold/v1beta9 +kind: Config +profiles: + - name: lemmy--dev + build: + artifacts: + - image: registry.gitlab.com/pojntfx/lemmy/server.dev + context: server + docker: + dockerfile: Dockerfile.dev + - image: registry.gitlab.com/pojntfx/lemmy/ui.dev + context: ui + docker: + dockerfile: Dockerfile.dev + sync: + "***/*.ts": . + "***/*.tsx": . + "***/*.css": . + deploy: + kubectl: + manifests: + - "**/*.dev.yaml" + - name: lemmy--prod + build: + artifacts: + - image: registry.gitlab.com/pojntfx/lemmy/server.prod + context: server + docker: + dockerfile: Dockerfile.prod + - image: registry.gitlab.com/pojntfx/lemmy/ui.prod + context: ui + docker: + dockerfile: Dockerfile.prod + deploy: + kubectl: + manifests: + - "**/*.prod.yaml" diff --git a/ui/Dockerfile.dev b/ui/Dockerfile.dev new file mode 100644 index 00000000..37f9e34c --- /dev/null +++ b/ui/Dockerfile.dev @@ -0,0 +1,12 @@ +# Setup env +FROM node:10-alpine +RUN mkdir -p /opt/lemmy/ui--dev +WORKDIR /opt/lemmy/ui--dev +# Install deps +COPY package.json . +COPY yarn.lock . +RUN npm install +# Add app +COPY . . +# Run app +CMD ["npm", "start"] diff --git a/ui/Dockerfile.prod b/ui/Dockerfile.prod new file mode 100644 index 00000000..9c478e67 --- /dev/null +++ b/ui/Dockerfile.prod @@ -0,0 +1,22 @@ +# Setup env +FROM node:10-alpine AS build +RUN mkdir -p /opt/lemmy/ui--prod +WORKDIR /opt/lemmy/ui--prod +# Install deps +COPY package.json . +COPY yarn.lock . +RUN npm install +# Add app +COPY . . +# Build app +RUN npm run build + +# Setup env +FROM node:10-alpine +RUN mkdir -p /opt/lemmy/ui--prod +WORKDIR /opt/lemmy/ui--prod +RUN npm install serve +# Add app +COPY --from=build /opt/lemmy/ui--prod/dist . +# Run app +CMD ["/opt/lemmy/ui--prod/node_modules/.bin/serve", "."] diff --git a/ui/stack.dev.yaml b/ui/stack.dev.yaml new file mode 100644 index 00000000..bb7c62e8 --- /dev/null +++ b/ui/stack.dev.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lemmy-ui--dev +spec: + selector: + matchLabels: + app: lemmy-ui--dev + template: + metadata: + labels: + app: lemmy-ui--dev + spec: + containers: + - name: lemmy-ui--dev + image: registry.gitlab.com/pojntfx/lemmy/ui.dev + resources: + limits: + memory: 1024Mi + cpu: 512m + ports: + - containerPort: 4444 +--- +apiVersion: v1 +kind: Service +metadata: + name: lemmy-ui--dev +spec: + type: NodePort + selector: + app: lemmy-ui--dev + ports: + - port: 4444 + nodePort: 30002 diff --git a/ui/stack.prod.yaml b/ui/stack.prod.yaml new file mode 100644 index 00000000..85ac6f6b --- /dev/null +++ b/ui/stack.prod.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lemmy-ui--prod +spec: + selector: + matchLabels: + app: lemmy-ui--prod + template: + metadata: + labels: + app: lemmy-ui--prod + spec: + containers: + - name: lemmy-ui--prod + image: registry.gitlab.com/pojntfx/lemmy/ui.prod + resources: + limits: + memory: 1024Mi + cpu: 512m + ports: + - containerPort: 4444 +--- +apiVersion: v1 +kind: Service +metadata: + name: lemmy-ui--prod +spec: + selector: + app: lemmy-ui--prod + ports: + - port: 5000 + targetPort: 5000 +--- +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: lemmy-server--prod + annotations: + traefik.ingress.kubernetes.io/request-modifier: "ReplacePathRegex: ^/static/(.*) /$1" +spec: + rules: + - host: dev.lemmy.local + http: + paths: + - path: / + backend: + serviceName: lemmy-ui--prod + servicePort: 5000 + - path: /service/ws + backend: + serviceName: lemmy-server--prod + servicePort: 8536