A link aggregator / reddit clone for the fediverse.
-[Lemmy Dev instance](https://dev.lemmy.ml) *for testing purposes only*
+[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) |
+| 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 [Kubernetes](#kubernetes)
+ - Comes with [Docker](#docker).
- Live-updating Comment threads.
- Full vote scores `(+/-)` like old reddit.
- Moderation abilities.
## Usage
-### Production
+### Kubernetes
-#### Docker
+#### Requirements
-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
+- 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/)
-<!-- #### Kubernetes (WIP)
+#### Production
-> TODO: Add production version with proper proxy setup and Ingress for WebSockets
+```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://${IP}:30002
-``` -->
-
-### Development
-
-#### 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/)
+Now go to http://dev.lemmy.local.
-##### Running
+#### Development
```bash
skaffold dev -p lemmy--dev
```
-And goto http://localhost:4444 (automatically proxies to localhost, both if the cluster is local or remote).
+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.
+
+### Docker
+
+Make sure you have both docker and docker-compose installed.
-It hot-reloads the UI and automatically recompiles the server.
+```
+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
-#### Non-Kubernetes
+### Native
-##### Requirements
+#### Requirements
- [Rust](https://www.rust-lang.org/)
- [Yarn](https://yarnpkg.com/en/)
- [Postgres](https://www.sqlite.org/index.html)
-##### Set up Postgres DB
+#### Set up Postgres DB
```
psql -c "create user rrr with password 'rrr' superuser;" -U postgres
psql -c 'create database rrr with owner rrr;' -U postgres
```
-##### Running
+#### Running
```
git clone https://github.com/dessalines/lemmy
# Setup env
-FROM rust:1.33
+FROM rust:1.33 AS build
RUN USER=root cargo new --bin /opt/lemmy/server--dev
WORKDIR /opt/lemmy/server--dev
-# Create empty directory where the frontend would normally be
-RUN mkdir -p /opt/lemmy/ui--dev/dist
# Enable deps caching
RUN mkdir -p src/bin
RUN echo 'fn main() { println!("Dummy") }' >src/bin/main.rs
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 ["/opt/lemmy/server--dev/target/release/lemmy"]
+CMD ["./lemmy"]
--- /dev/null
+# 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"]
--- /dev/null
+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
deploy:
kubectl:
manifests:
- - server/stack.dev.yaml
- - ui/stack.dev.yaml
+ - "**/*.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"
# Setup env
-FROM node:10
+FROM node:10-alpine
RUN mkdir -p /opt/lemmy/ui--dev
WORKDIR /opt/lemmy/ui--dev
# Install deps
# Add app
COPY . .
# Run app
-CMD npm start
+CMD ["npm", "start"]
--- /dev/null
+# 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", "."]
--- /dev/null
+---
+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