mirror of
https://github.com/LemmyNet/lemmy-docs.git
synced 2024-11-21 20:01:10 +00:00
Lemmy Docs Indonesian First Translation (#120)
This commit is contained in:
parent
47aaf77354
commit
5cd028069b
38 changed files with 1970 additions and 0 deletions
|
@ -13,3 +13,7 @@ title = "Documentación Lemmy"
|
|||
[language.ru]
|
||||
name = "Русский"
|
||||
title = "Документация Lemmy"
|
||||
|
||||
[language.id]
|
||||
name = "Indonesia"
|
||||
title = "Dokumentasi Lemmy"
|
||||
|
|
31
src/id/SUMMARY.md
Normal file
31
src/id/SUMMARY.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Ringkasan
|
||||
|
||||
- [Tentang](about/about.md)
|
||||
- [Fitur](about/features.md)
|
||||
- [Ranking Pos dan Komentar](about/ranking.md)
|
||||
- [Panduan](about/guide.md)
|
||||
- [Administrasi](administration/administration.md)
|
||||
- [Pasang menggunakan Docker](administration/install_docker.md)
|
||||
- [Pasang menggunakan Ansible](administration/install_ansible.md)
|
||||
- [Pasang dari Awal](administration/from_scratch.md)
|
||||
- [Pasang di AWS](administration/on_aws.md)
|
||||
- [Langkah Pertama](administration/first_steps.md)
|
||||
- [Konfigurasi](administration/configuration.md)
|
||||
- [Memulai dengan Federasi](administration/federation_getting_started.md)
|
||||
- [Penyelesaian Masalah](administration/troubleshooting.md)
|
||||
- [Cadangan dan Pemulihan](administration/backup_and_restore.md)
|
||||
- [Federasi](federation/federation.md)
|
||||
- [Tinjauan Federasi](federation/overview.md)
|
||||
- [Protokol Lemmy](federation/lemmy_protocol.md)
|
||||
- [Pengembangan Klien](client_development/client_development.md)
|
||||
- [Ekstra API HTTP](client_development/http_api_extras.md)
|
||||
- [Panduan Membuat Tema](client_development/theming.md)
|
||||
- [Membuat Tampilan Depan Kustom](client_development/custom_frontend.md)
|
||||
- [Kontribusi](contributing/contributing.md)
|
||||
- [Pengembangan Docker](contributing/docker_development.md)
|
||||
- [Pengembangan Lokal](contributing/local_development.md)
|
||||
- [Pengujian](contributing/tests.md)
|
||||
- [Pengembangan Federasi](contributing/federation_development.md)
|
||||
- [Proses Rilis](contributing/release_process.md)
|
||||
- [Sumber/Pustaka](contributing/resources.md)
|
||||
- [Kode Etik](code_of_conduct.md)
|
34
src/id/about/about.md
Normal file
34
src/id/about/about.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
## Tentang Proyek Ini
|
||||
|
||||
Halaman Depan|Pos
|
||||
---|---
|
||||
![layar utama](main_screen.png)|![layar percakapan](chat_screen.png)
|
||||
|
||||
[Lemmy](https://github.com/LemmyNet/lemmy) serupa seperti situs seperti [Reddit](https://reddit.com), [Lobste.rs](https://lobste.rs), [Raddle](https://raddle.me), atau [Hacker News](https://news.ycombinator.com/): Anda berlangganan ke forum yang Anda tertarik kepada mereka, pos tautan dan diskusi, kemudian pilih, dan komentar di sana. Di belakang layar, itu sangat berbeda; semua orang bisa dengan mudah menjalankan sebuah peladen dan semua peladen tersebut terfederasi (seperti surel) dan terhubung ke semesta yang sama, yaitu [Fediverse](https://en.wikipedia.org/wiki/Fediverse).
|
||||
|
||||
*Kata “fediverse” (federated universe) merujuk kepada jaringan dari semua peladen Lemmy [dan proyek lainnya](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/), yang dimana pengguna bisa berbicara satu sama lain dengan seamlessly.*
|
||||
|
||||
Seperti surel, entah Anda mendaftar di Gmail atau Outlook, Anda tahu Anda akan bisa mengirim surel ke semua yang Anda butuhkan, asalkan Anda tahu alamat mereka. Di Lemmy, Anda bisa berlangganan ke komunitas di peladen mana pun lainnya dan bisa mengikuti diskusi dengan pengguna terdaftar dimana pun.
|
||||
|
||||
Tujuan utama proyek ini adalah untuk membuat alternatif dari Reddit dan pengumpul tautan lainnya yang mudah dihos sendiri dan desentralisasi, tanpa satu pun perusahaan yang menjalankan pertunjukan.
|
||||
|
||||
Tidak ada pemegang modal dan tidak ada iklan tertarget: hanya orang yang membagikan hal yang mereka ingin bagikan dengan yang lainnya.
|
||||
|
||||
Setiap peladen Lemmy bisa menentukan kebijakan moderasinya sendiri-sendiri; mengangkat admin tingkat situs, moderator komunitas untuk waspada terhadap troll, dan memupuk lingkungan yang sehat di mana semua bisa dengan nyaman berkontribusi.
|
||||
|
||||
*Catatan: Federasi masih dalam pengembangan aktif*
|
||||
|
||||
### Kenapa dinamai Lemmy?
|
||||
|
||||
- Penyanyi utama [Motörhead](https://invidio.us/watch?v=pWB5JZRGl0U).
|
||||
- [Permainan video klasik](<https://en.wikipedia.org/wiki/Lemmings_(video_game)>).
|
||||
- [Koopa dari Super Mario](https://www.mariowiki.com/Lemmy_Koopa).
|
||||
- [Hewan pengerat berbulu](http://sunchild.fpwc.org/lemming-the-little-giant-of-the-north/).
|
||||
|
||||
### Dibangun menggunakan
|
||||
|
||||
- [Rust](https://www.rust-lang.org)
|
||||
- [Actix](https://actix.rs/)
|
||||
- [Diesel](http://diesel.rs/)
|
||||
- [Inferno](https://infernojs.org)
|
||||
- [Typescript](https://www.typescriptlang.org/)
|
BIN
src/id/about/chat_screen.png
Normal file
BIN
src/id/about/chat_screen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
35
src/id/about/features.md
Normal file
35
src/id/about/features.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Fitur
|
||||
|
||||
- Sumber terbuka, [Lisensi AGPL](/LICENSE).
|
||||
- Bisa disetel sendiri, mudah untuk dipasang.
|
||||
- Dibundel dengan [Docker](../administration/install_docker.md) dan [Ansible](../administration/install_ansible.md).
|
||||
- Tampilan yang bersih dan ramah ponsel.
|
||||
- Yang dibutuhkan untuk mendaftar adalah nama pengguna dan kata sandi!
|
||||
- Dukungan avatar pengguna.
|
||||
- Utas komentar dengan pembaruan langsung.
|
||||
- Skor pilihan penuh `(+/-)` seperti Reddit yang lama.
|
||||
- Banyak tema, termasuk terang, gelap, dan solarized.
|
||||
- Emoji dengan dukungan ketik otomatis. Mulai mengetik `:`
|
||||
- Tandai pengguna menggunakan `@`, tandai komunitas menggunakan `!`.
|
||||
- Pengunggahan gambar terintegrasi baik di pos atau komentar.
|
||||
- Sebuah pos bisa terdiri dari sebuah judul dan kombinasi dari teks subjek, URL, atau tidak ada teks sama sekali.
|
||||
- Notifikasi di balasan komentar dan ketika Anda ditandai.
|
||||
- Notifikasi bisa dikirim lewat surel.
|
||||
- i18n/dukungan penginternasionalan
|
||||
- Umpan RSS/Atom untuk `Semua`, `Berlangganan`, `Kotak Masuk`, `Pengguna`, dan `Komunitas`.
|
||||
- Dukungan pos-lintas.
|
||||
- Sebuah *pencarian pos serupa* ketika membuat pos baru. Bagus untuk komunitas tanya/jawab.
|
||||
- Kemampuan moderasi.
|
||||
- Log Moderasi Publik.
|
||||
- Bisa melengketkan pos ke bagian atas komunitas.
|
||||
- Baik admin situs dan moderator komunitas dapat menunjuk moderator lain.
|
||||
- Bisa mengunci, menghapus, dan memulihkan pos dan komentar.
|
||||
- Bisa melarang dan batal melarang pengguna dari komunitas dan situs.
|
||||
- Bisa memindah situs dan komunitas ke yang lain.
|
||||
- Bisa menghapus seluruhnya data Anda, menggantikan seluruh pos dan komentar.
|
||||
- Dukungan pos/komunitas NSFW
|
||||
- Performa tinggi.
|
||||
- Peladen ditulis dengan Rust.
|
||||
- Antarmuka `~80kB` gzipped.
|
||||
- Antarmuka bekerja tanpa JavaScript (hanya-baca)
|
||||
- Mendukung arm64/Raspberry Pi.
|
95
src/id/about/guide.md
Normal file
95
src/id/about/guide.md
Normal file
|
@ -0,0 +1,95 @@
|
|||
# Panduan Mulai Cepat Lemmy
|
||||
|
||||
Jadi Anda ingin bergabung dengan Lemmy dan mulai mengepos. Bagus! Begini cara untuk meluncur masuk.
|
||||
|
||||
## Di mana saya mendaftar?
|
||||
|
||||
Hal pertama yang Anda harus lakukan adalah **memilih peladen Anda**. Ini merupakan langkah tambahan dibandingkan dengan situs seperti Reddit, tapi tidak sesulit yang dikira.
|
||||
|
||||
*Seperti surel, identitas Anda dihos oleh peladen yang dimana Anda mendaftar. Jadi sebagai contoh, saya gabung ke lemmy.ml, jadi untuk menyebutkan saya, Anda bisa mengetikkan @retiolus@lemmy.ml di pos Anda.*
|
||||
|
||||
Jika apa yang ingin Anda bicarakan sesuai dengan kategori yang jelas (mungkin itu permainan video atau seni atau kehidupan aneh atau pengkodean atau fiksi, dll.) maka mungkin ada baiknya membuat peladen pertama Anda di mana yang terutama akan menampung konten semacam itu – akan lebih mudah untuk membuat koneksi dan menemukan orang-orang yang berpikiran sama. Pikirkan peladen Anda sebagai lingkungan atau tempat, di mana obrolan umum tersebut dapat memiliki fokus khusus.
|
||||
|
||||
*Anda memiliki kemampuan untuk melihat semua pos lokal publik yang dibuat oleh orang di peladen Anda di bilah "Lokal".*
|
||||
|
||||
Jika Anda tidak di sini untuk menempel ke satu topik, Anda mungkin ingin memilih peladen yang melayani percakapan umum. Apa pun itu, ada daftar peladen yang berguna di [join-lemmy.org](https://join-lemmy.org/instances).
|
||||
|
||||
**Jangan panik!** Anda bisa berbicara kepada orang di peladen lainnya, tidak peduli apa yang Anda pilih. Ingat, ini seperti surel dan, contohnya, Anda masih bisa mengirim surel kepada ibu Anda di akun Yahoo kuno dari Gmail Anda.
|
||||
|
||||
## Ketahui peladen Anda
|
||||
|
||||
Luangkan waktu sejenak sebelum mendaftar untuk memeriksa peraturan dari peladen pilihan Anda dan pastikan mereka sesuai dengan bagaimana Anda ingin mengepos.
|
||||
|
||||
Peladen biasanya mendefinisikan peraturan mereka dengan cara yang simpel di bilah sisi kanan dari situs. Dari atas ke bawah, Anda akan biasanya menemukan daftar "Komunitas Sedang Tren" diikuti oleh "Berlangganan ke komunitas," deskripsi singkat peladen, peraturan, beberapa statistik, dan nama pengguna dari admin.
|
||||
|
||||
Admin merupakan orang yang sangat ramah yang bisanya menjalankan peladen dari dompet mereka sendiri, jadi merupakan hal yang bagus untuk mengenal mereka. Banyak dari mereka yang menerima donasi untuk menutupi biaya operasional dan jika Anda bisa berkontribusi maka hal itu selalu dihargai.
|
||||
|
||||
## Sepertinya saya menemukan rumah baru saya!
|
||||
|
||||
Pergi ke halaman Masuk `(https://your.server/login)` dari peladen Anda dan pilih nama pengguna dan kata sandi di formulir pendaftaran. Anda tidak perlu sebuah surel untuk mendaftar, tapi itu merupakan satu-satunya cara untuk mengatur ulang kata sandi Anda jika Anda kehilangannya.
|
||||
|
||||
Hal selanjutnya untuk dilakukan adalah mengunggah gambar profil Anda, berikan halaman pengaturan `(https://your.server/settings)` sebuah utak-atik (dan kembali melakukannya ketika Anda sudah di Lemmy selama beberapa pekan atau hanya untuk utak-atik yang mungkin membantu pengalaman Anda) dan bersiaplah untuk mengenalkan diri Anda.
|
||||
|
||||
*Beberapa pengaturan yang menarik untuk diperiksa adalah: jenis filter umpan baku antara berlangganan, lokal, atau semua dan jenis pengurutan baku Anda*
|
||||
|
||||
Meskipun Anda bisa hanya santai membaca Lemmy, keseruan yang asli dimulai ketika Anda meluncur dan mulai berpartisipasi dengan mengepos, mengeluarkan pilihan, dan berkomentar
|
||||
|
||||
Untuk membagikan sebuah pos, klik tombol "Buat Pos" di sisi atas dari layar. Anda akan dibawa ke sebuah formulir di mana Anda bisa memasukkan URL dari tautan atau mengunggah gambar Anda dan memasukkan judul dan badan pos. Anda juga akan diharuskan untuk memasukkan sebuah komunitas di mana Anda ingin pos Anda muncul. Sebelum melakukan itu, merupakan ide yang bagus untuk menuju ke halaman komunitas tersebut dan membaca panduan mengepos yang ada di sebelah kanan layar. Ini akan memastikan bahwa Anda patuh terhadap etos tertentu dari sebuah komunitas. Contohnya, di komunitas [`!privacy@lemmy.ml`](https://lemmy.ml/c/privacy), Anda tidak boleh untuk mempromosikan perangkat lunak tidak bebas.
|
||||
|
||||
Ketika semua bagian sudah diisi, klik "Buat" dan pos Anda akan muncul.
|
||||
|
||||
Ketika menulis sebuah pos atau komentar baru, mulai mengetik...
|
||||
|
||||
- `@a_user_name` untuk mendapatkan daftar nama pengguna.
|
||||
- `!a_community` untuk mendapatkan daftar komunitas.
|
||||
- `:emoji` untuk mendapatkan daftar emoji.
|
||||
|
||||
## Pengenalan cepat tampilan web
|
||||
|
||||
![interface.png](interface.png)
|
||||
|
||||
Tampilan standar Lemmy memiliki satu umpan. Anda bisa mengubah konten dari umpan tersebut menggunakan filter:
|
||||
|
||||
**Berlangganan** termasuk pos dari peladen Anda dan peladen lainnya, yang terpenting adalah komunitas yang Anda ikuti.
|
||||
|
||||
**Lokal** adalah umpan dari semua pos di komunitas di peladen Anda. Di banyak peladen, terutama yang kecil-kecil dan terfokus ke topik tertentu, di sinilah sihir terjadi. Anda bisa membalas ke orang dari sana dan di sana merupakan tempat yang bagus untuk bertemu dengan orang yang berbagi minat yang sama denganmu.
|
||||
|
||||
**Semua** atau **lini masa terfederasi** adalah untuk melihat semua pos publik yang peladen Anda ketahui dari seluruh jaringan (termasuk yang lokal). Alasan yang paling umum ketika sesuatu tampil di lini masa terfederasi adalah ada seseorang dari peladen Anda mengikuti komunitas yang ada di peladen lainnya.
|
||||
|
||||
| Jenis | Deskripsi |
|
||||
| --- | --- |
|
||||
| Pos | Hanya tampilkan publikasi (pos) |
|
||||
| Komentar | Hanya tampilkan komentar |
|
||||
| \-\-\- | \-\-\- |
|
||||
| Aktif | Urut yang tren berdasarkan skor dan waktu komentar yang paling baru. |
|
||||
| Hangat | Urut yang tren berdasarkan skor dan waktu pembuatan pos. |
|
||||
| Baru | Yang terbaru. |
|
||||
| Paling Banyak Komentar | Pos dengan komentar paling banyak. |
|
||||
| Komentar Terbaru | Pos dengan komentar yang paling baru, alias urut gaya-forum. |
|
||||
| Teratas | Skor terbesar di jangka waktu tertentu. |
|
||||
|
||||
Untuk detail lebih lanjut, periksa [detail Ranking Pos dan Komentar](ranking.md).
|
||||
|
||||
## Menggunakan Markdown
|
||||
|
||||
Pos Lemmy ditulis menggunakan Markdown, tentu saja ada pintasan untuk Anda gunakan ketika menulis, di bawah ini merupakan tabel untuk membantu Anda jika Anda ingin tahu lebih lanjut.
|
||||
|
||||
Ketik | Atau | … untuk mendapatkan
|
||||
--- | --- | ---
|
||||
\*Miring\* | \_Miring\_ | _Miring_
|
||||
\*\*Tebal\*\* | \_\_Tebal\_\_ | **Tebal**
|
||||
\# Tajuk 1 | Tajuk 1 <br> ========= | <h4>Tajuk 1</h4>
|
||||
\## Tajuk 2 | Tajuk 2 <br>--------- | <h5>Tajuk 2</h5>
|
||||
\[Tautan\](http://a.com) | \[Tautan\]\[1\]<br>⋮ <br>\[1\]: http://b.org | [Tautan](https://commonmark.org/)
|
||||
!\[Gambar\](http://url/a.png) | !\[Gambar\]\[1\]<br>⋮ <br>\[1\]: http://url/b.jpg | ![Markdown](https://commonmark.org/help/images/favicon.png)
|
||||
\> Kutipan | | <blockquote>Kutipan</blockquote>
|
||||
\* Daftar <br>\* Daftar <br>\* Daftar | \- Daftar <br>\- Daftar <br>\- Daftar <br> | * Daftar <br>* Daftar <br>* Daftar <br>
|
||||
1\. Satu <br>2\. Dua <br>3\. Tiga | 1) Satu<br>2) Dua<br>3) Tiga | 1. Satu<br>2. Dua<br>3. Tiga
|
||||
Garis Horizontal <br>\--- | Garis Horizontal<br>\*\*\* | Garis Horizontal <br><hr>
|
||||
\`Kode di pos\` dengan petik terbalik | |`Kode di pos` dengan petik terbalik
|
||||
\`\`\`<br>\# blok kode <br>print '3 petik terbalik or'<br>print 'indentasi 4 spasi' <br>\`\`\` | ····\# blok kode<br>····print '3 petik terbalik or'<br>····print 'indentasi 4 spasi' | \# blok kode <br>print '3 petik terbalik or'<br>print 'indentasi 4 spasi'
|
||||
::: spoiler sembunyi atau sesuatu porno<br>*sesuatu untuk disembunyikan*<br>::: | | <details><summary> sembunyi atau sesuatu porno </summary><p><em>sesuatu untuk disembunyikan</em></p></details>
|
||||
Teks ~bawah~ garis | | Teks <sub>bawah</sub> garis
|
||||
Teks ^atas^ garis | | Teks <sup>atas</sup> garis
|
||||
|
||||
[Tutorial CommonMark](https://commonmark.org/help/tutorial/)
|
BIN
src/id/about/interface.png
Normal file
BIN
src/id/about/interface.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
BIN
src/id/about/main_screen.png
Normal file
BIN
src/id/about/main_screen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
BIN
src/id/about/rank_algorithm.png
Normal file
BIN
src/id/about/rank_algorithm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
46
src/id/about/ranking.md
Normal file
46
src/id/about/ranking.md
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Trending / Hot / Best Sorting algorithm
|
||||
|
||||
## Goals
|
||||
|
||||
- During the day, new posts and comments should be near the top, so they can be voted on.
|
||||
- After a day or so, the time factor should go away.
|
||||
- Use a log scale, since votes tend to snowball, and so the first 10 votes are just as important as the next hundred.
|
||||
|
||||
## Implementations
|
||||
|
||||
### Reddit
|
||||
|
||||
Does not take the lifetime of the thread into account, [giving early comments an overwhelming advantage over later ones,](https://minimaxir.com/2016/11/first-comment/) with the effect being even worse in small communities. New comments pool at the bottom of the thread, effectively killing off discussion and making each thread a race to comment early. This lowers the quality of conversation and rewards comments that are repetitive and spammy.
|
||||
|
||||
### Hacker News
|
||||
|
||||
While far superior to Reddit's implementation for its decay of scores over time, [Hacker News' ranking algorithm](https://medium.com/hacking-and-gonzo/how-hacker-news-ranking-algorithm-works-1d9b0cf2c08d) does not use a logarithmic scale for scores.
|
||||
|
||||
### Lemmy
|
||||
|
||||
Counterbalances the snowballing effect of votes over time with a logarithmic scale. Negates the inherent advantage of early comments while still ensuring that votes still matter in the long-term, not nuking older popular comments.
|
||||
|
||||
```
|
||||
Rank = ScaleFactor * log(Max(1, 3 + Score)) / (Time + 2)^Gravity
|
||||
|
||||
Score = Upvotes - Downvotes
|
||||
Time = time since submission (in hours)
|
||||
Gravity = Decay gravity, 1.8 is default
|
||||
```
|
||||
- Lemmy uses the same `Rank` algorithm above, in two sorts: `Active`, and `Hot`.
|
||||
- `Active` uses the post votes, and latest comment time (limited to two days).
|
||||
- `Hot` uses the post votes, and the post published time.
|
||||
- Use Max(1, score) to make sure all comments are affected by time decay.
|
||||
- Add 3 to the score, so that everything that has less than 3 downvotes will seem new. Otherwise all new comments would stay at zero, near the bottom.
|
||||
- The sign and abs of the score are necessary for dealing with the log of negative scores.
|
||||
- A scale factor of 10k gets the rank in integer form.
|
||||
|
||||
A plot of rank over 24 hours, of scores of 1, 5, 10, 100, 1000, with a scale factor of 10k.
|
||||
|
||||
![](rank_algorithm.png)
|
||||
|
||||
#### Active User counts
|
||||
|
||||
Lemmy also shows counts of *active users* for your site, and its communities. These are counted within the last `day`, `week`, `month`, and `half year`, and are cached on starting up lemmy, and every hour.
|
||||
|
||||
An active user is someone who has posted or commented on our instance or community within the last given time frame. For site counts, only local users are counted. For community counts, federated users are included.
|
19
src/id/administration/administration.md
Normal file
19
src/id/administration/administration.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Informasi Administrasi
|
||||
|
||||
Informasi untuk admin peladen Lemmy dan mereka yang ingin menjalankan sebuah peladen.
|
||||
|
||||
## Pasang
|
||||
### Metode Resmi/Didukung
|
||||
|
||||
Lemmy memiliki dua metode pemasangan utama:
|
||||
- [Manual dengan Docker](install_docker.md)
|
||||
- [Otomatis dengan Ansible](install_ansible.md)
|
||||
|
||||
Kami merekomendasikan menggunakan Ansible, karena menyederhanakan instalasi dan juga membuat pembaruan lebih mudah.
|
||||
|
||||
### Metode pemasangan lainnya
|
||||
> ⚠️ **Hati-hati! Risiko Anda sendiri**
|
||||
|
||||
Dalam beberapa kasus, mungkin perlu menggunakan metode pemasangan yang berbeda. Tetapi kami tidak merekomendasikan ini, dan tidak dapat memberikan dukungan untuk mereka.
|
||||
- [Dari Awal](from_scratch.md)
|
||||
- [Di Amazon Web Services (AWS)](on_aws.md)
|
77
src/id/administration/backup_and_restore.md
Normal file
77
src/id/administration/backup_and_restore.md
Normal file
|
@ -0,0 +1,77 @@
|
|||
# Backup and Restore Guide
|
||||
|
||||
## Docker and Ansible
|
||||
|
||||
When using docker or ansible, there should be a `volumes` folder, which contains both the database, and all the pictures. Copy this folder to the new instance to restore your data.
|
||||
|
||||
### Incremental Database backup
|
||||
|
||||
To incrementally backup the DB to an `.sql` file, you can run:
|
||||
|
||||
```bash
|
||||
docker-compose exec postgres pg_dumpall -c -U lemmy > lemmy_dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql
|
||||
```
|
||||
### A Sample backup script
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
# DB Backup
|
||||
ssh MY_USER@MY_IP "docker-compose exec postgres pg_dumpall -c -U lemmy" > ~/BACKUP_LOCATION/INSTANCE_NAME_dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql
|
||||
|
||||
# Volumes folder Backup
|
||||
rsync -avP -zz --rsync-path="sudo rsync" MY_USER@MY_IP:/LEMMY_LOCATION/volumes ~/BACKUP_LOCATION/FOLDERNAME
|
||||
```
|
||||
|
||||
### Restoring the DB
|
||||
|
||||
If you need to restore from a `pg_dumpall` file, you need to first clear out your existing database
|
||||
|
||||
```bash
|
||||
# Drop the existing DB
|
||||
docker exec -i FOLDERNAME_postgres_1 psql -U lemmy -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
|
||||
|
||||
# Restore from the .sql backup
|
||||
cat db_dump.sql | docker exec -i FOLDERNAME_postgres_1 psql -U lemmy # restores the db
|
||||
|
||||
# This also might be necessary when doing a db import with a different password.
|
||||
docker exec -i FOLDERNAME_postgres_1 psql -U lemmy -c "alter user lemmy with password 'bleh'"
|
||||
```
|
||||
|
||||
### Changing your domain name
|
||||
|
||||
If you haven't federated yet, you can change your domain name in the DB. **Warning: do not do this after you've federated, or it will break federation.**
|
||||
|
||||
Get into `psql` for your docker:
|
||||
|
||||
`docker-compose exec postgres psql -U lemmy`
|
||||
|
||||
```
|
||||
-- Post
|
||||
update post set ap_id = replace (ap_id, 'old_domain', 'new_domain');
|
||||
update post set url = replace (url, 'old_domain', 'new_domain');
|
||||
update post set body = replace (body, 'old_domain', 'new_domain');
|
||||
update post set thumbnail_url = replace (thumbnail_url, 'old_domain', 'new_domain');
|
||||
|
||||
-- Comments
|
||||
update comment set ap_id = replace (ap_id, 'old_domain', 'new_domain');
|
||||
update comment set content = replace (content, 'old_domain', 'new_domain');
|
||||
|
||||
-- User
|
||||
update user_ set actor_id = replace (actor_id, 'old_domain', 'new_domain');
|
||||
update user_ set inbox_url = replace (inbox_url, 'old_domain', 'new_domain');
|
||||
update user_ set shared_inbox_url = replace (shared_inbox_url, 'old_domain', 'new_domain');
|
||||
update user_ set avatar = replace (avatar, 'old_domain', 'new_domain');
|
||||
|
||||
-- Community
|
||||
update community set actor_id = replace (actor_id, 'old_domain', 'new_domain');
|
||||
update community set followers_url = replace (followers_url, 'old_domain', 'new_domain');
|
||||
update community set inbox_url = replace (inbox_url, 'old_domain', 'new_domain');
|
||||
update community set shared_inbox_url = replace (shared_inbox_url, 'old_domain', 'new_domain');
|
||||
|
||||
```
|
||||
|
||||
## More resources
|
||||
|
||||
- https://stackoverflow.com/questions/24718706/backup-restore-a-dockerized-postgresql-database
|
||||
|
||||
|
20
src/id/administration/configuration.md
Normal file
20
src/id/administration/configuration.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Configuration
|
||||
|
||||
The configuration is based on the file config.hjson, which is located by default at `config/config.hjson`. To change the default location, you can set the environment variable `LEMMY_CONFIG_LOCATION`.
|
||||
|
||||
An additional environment variable `LEMMY_DATABASE_URL` is available, which can be used with a PostgreSQL connection string like `postgres://lemmy:password@lemmy_db:5432/lemmy`, passing all connection details at once.
|
||||
|
||||
If the Docker container is not used, manually create the database specified above by running the following commands:
|
||||
|
||||
```bash
|
||||
cd server
|
||||
./db-init.sh
|
||||
```
|
||||
|
||||
**Federation is not set up by default.** You can add this [this federation block](https://github.com/lemmynet/lemmy/blob/main/config/config.hjson#L64) to your `lemmy.hjson`, and ask other servers to add you to their allowlist.
|
||||
|
||||
## Full config with default values
|
||||
|
||||
```hjson
|
||||
{{#include ../../../include/config/defaults.hjson}}
|
||||
```
|
45
src/id/administration/federation_getting_started.md
Normal file
45
src/id/administration/federation_getting_started.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Federation
|
||||
|
||||
Lemmy has three types of federation:
|
||||
|
||||
- Allowlist: Explicitly list instances to connect to.
|
||||
- BlockList: Explicitly list instances to not connect to. Federation is open to all other instances.
|
||||
- Open: Federate with all potential instances.
|
||||
|
||||
**Federation is not set up by default.** You can add this [this federation block](https://github.com/lemmynet/lemmy/blob/main/config/config.hjson#L64) to your `lemmy.hjson`, and ask other servers to add you to their allowlist.
|
||||
|
||||
Lemmy uses the ActivityPub protocol (a W3C standard) to enable federation between different servers (often called instances). This is very similar to the way email works. For example, if you use gmail.com, then you can not only send mails to other gmail.com users, but also to yahoo.com, yandex.ru and so on. Email uses the SMTP protocol to achieve this, so you can think of ActivityPub as "SMTP for social media". The amount of different actions possible on social media (post, comment, like, share, etc) means that ActivityPub is much more complicated than SMTP.
|
||||
|
||||
As with email, ActivityPub federation happens only between servers. So if you are registered on `enterprise.lemmy.ml`, you only connect to the API of `enterprise.lemmy.ml`, while the server takes care of sending and receiving data from other instances (eg `voyager.lemmy.ml`). The great advantage of this approach is that the average user doesn't have to do anything to use federation. In fact if you are using Lemmy, you are likely already using it. One way to confirm is by going to a community or user profile. If you are on `enterprise.lemmy.ml` and you see a user like `@nutomic@voyager.lemmy.ml`, or a community like `!main@ds9.lemmy.ml`, then those are federated, meaning they use a different instance from yours.
|
||||
|
||||
One way you can take advantage of federation is by opening a different instance, like `ds9.lemmy.ml`, and browsing it. If you see an interesting community, post or user that you want to interact with, just copy its URL and paste it into the search of your own instance. Your instance will connect to the other one (assuming the allowlist/blocklist allows it), and directly display the remote content to you, so that you can follow a community or comment on a post. Here are some examples of working searches:
|
||||
|
||||
- `!main@lemmy.ml` (Community)
|
||||
- `@nutomic@lemmy.ml` (User)
|
||||
- `https://lemmy.ml/c/programming` (Community)
|
||||
- `https://lemmy.ml/u/nutomic` (User)
|
||||
- `https://lemmy.ml/post/123` (Post)
|
||||
- `https://lemmy.ml/comment/321` (Comment)
|
||||
|
||||
You can see the list of linked instances by following the "Instances" link at the bottom of any Lemmy page.
|
||||
|
||||
## Fetching communities
|
||||
|
||||
If you search for a community first time, 20 posts are fetched initially. Only if a least one user on your instance subscribes to the remote community, will the community send updates to your instance. Updates include:
|
||||
|
||||
- New posts, comments
|
||||
- Votes
|
||||
- Post, comment edits and deletions
|
||||
- Mod actions
|
||||
|
||||
You can copy the URL of the community from the address bar in your browser and insert it in your search field. Wait a few seconds, the post will appear below. At the moment there is no loading indicator for the search, so wait a few seconds if it shows "no results".
|
||||
|
||||
## Fetching posts
|
||||
|
||||
Paste the URL of a post into your Lemmy instance's search field. Wait a few seconds until the post appears. This will also fetch the community profile, and the profile of the post creator.
|
||||
|
||||
## Fetching comments
|
||||
|
||||
If you find an interesting comment under a posting on another instance, you can find below the comment in the 3-dot-menu the link-symbol. Copy this link. It looks like `https://lemmy.ml/post/56382/comment/40796`. Remove the `post/XXX` part and put it into your search-bar. For this example, search for `https://lemmy.ml/comment/40796`. This comment, all parent comments, users and community and the corresponding post are fetched from the remote instance, if they are not known locally.
|
||||
|
||||
Sibling comments are not fetched! If you want more comments from older posts, you have to search for each of them as described above.
|
44
src/id/administration/first_steps.md
Normal file
44
src/id/administration/first_steps.md
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Administration First Steps
|
||||
|
||||
After you successfully installed Lemmy either [manually with Docker](administration/install_docker.html) or [automatically with Ansible](administration/install_ansible.html) here are some recommendations for a new administrator of a Lemmy server.
|
||||
|
||||
## Admin Settings
|
||||
|
||||
The first thing to do is to go to your admin panel, which can be found by clicking on the cog at the top right next to the search icon. Here you can define a description for your site, so that people know if it is about one specific topic or if all subjects are welcome. You can also add an icon and a banner that define your server, it can for example be the logo of your organization.
|
||||
|
||||
Take the time to browse through the entire page to discover the different options you have to customize your Lemmy instance, on the same page you can edit your [configuration file](configuration.html), where you can find information about your database, the email used by the server, the federation options or who is the main administrator.
|
||||
|
||||
It is always good to define another administrator than yourself, in case it is necessary to take actions while you take your best nap. Take a look at the [moderation guide](../moderation/moderation.html) for more information on how to do this.
|
||||
|
||||
## Check that everything is working properly
|
||||
|
||||
### Email
|
||||
|
||||
The easiest way to check that the email is set up correctly is to request a password renewal. You will need to set up an email in your settings if you have not already done so.
|
||||
|
||||
After that just log out, go to the `Login` page, enter your email in the `Email or Username` box and press `forgot password`. If everything is set up correctly, you should receive an email to renew your password. You can ignore this email.
|
||||
|
||||
### Federation
|
||||
|
||||
Federation is disabled by default, and needs to be enabled either through the online admin panel or directly through the `config.json` file.
|
||||
|
||||
To test that your instance federation is working correctly execute `curl -H 'Accept: application/activity+json' https://your-instance.com/u/your-username`, it should return json data, and not an .html file. If that is unclear to you, it should look similar to the output of `curl -H 'Accept: application/activity+json' https://lemmy.ml/u/nutomic`.
|
||||
|
||||
## Inclusion on join-lemmy.org instance list
|
||||
|
||||
To be included in the list of Lemmy instances on [join-lemmy.org](https://join-lemmy.org/instances) you must meet the following requirements:
|
||||
- [x] Federate with at least one instance from the list
|
||||
- [x] Have a site description and icon
|
||||
- [x] Be patient and wait the site to be updated, there's no fixed schedule for that
|
||||
|
||||
In the meantime you can always promote your server on other social networks like Mastodon using the hashtag `#Lemmy`.
|
||||
|
||||
## Keeping up to date
|
||||
|
||||
You can subscribe to the Github RSS feeds to be informed of the latest releases:
|
||||
- [lemmy](https://github.com/LemmyNet/lemmy/releases.atom)
|
||||
- [lemmy-ui](https://github.com/LemmyNet/lemmy-ui/releases.atom)
|
||||
- [lemmy-js-client](https://github.com/LemmyNet/lemmy-js-client/releases.atom)
|
||||
- [joinlemmy-site](https://github.com/LemmyNet/joinlemmy-site/releases.atom)
|
||||
|
||||
There is also a [Matrix chat](https://matrix.to/#/!OwmdVYiZSXrXbtCNLw:matrix.org) for instance administrators that you can join. You'll find some really friendly people there who will help you (or at least try to) if you run into any issue.
|
239
src/id/administration/from_scratch.md
Normal file
239
src/id/administration/from_scratch.md
Normal file
|
@ -0,0 +1,239 @@
|
|||
# From Scratch
|
||||
|
||||
> ⚠️ **Disclaimer:** this installation method is not recommended by the Lemmy developers. If you have any problems, you need to solve them yourself or ask the respective authors. If you notice any Lemmy bugs on an instance installed like this, please mention it in the bug report.
|
||||
|
||||
These instructions are written for Ubuntu 20.04.
|
||||
|
||||
## Installation
|
||||
|
||||
### Lemmy Backend
|
||||
|
||||
It is built from source, so this may take a while, especially on slow devices. For example, Lemmy v0.12.2 takes 17 minutes to build on a dual core VPS. If you prefer prebuilt binaries, use Docker.
|
||||
|
||||
Compile and install Lemmy, setup database:
|
||||
```bash
|
||||
apt install pkg-config libssl-dev libpq-dev cargo postgresql
|
||||
# installs latest release, you can also specify one with --version
|
||||
# The --locked argument uses the exact versions of dependencies specified in
|
||||
# `cargo.lock`at release time. Running it without the flag will use newer minor
|
||||
# release versions of those dependencies, which are not always guaranteed to compile.
|
||||
cargo install lemmy_server --target-dir /usr/bin/ --locked
|
||||
# replace db-passwd with a randomly generated password
|
||||
sudo -iu postgres psql -c "CREATE USER lemmy WITH PASSWORD 'db-passwd';"
|
||||
sudo -iu postgres psql -c "CREATE DATABASE lemmy WITH OWNER lemmy;"
|
||||
adduser lemmy --system --disabled-login --no-create-home --group
|
||||
```
|
||||
|
||||
Minimal Lemmy config, put this in `/etc/lemmy/lemmy.hjson` (see [here](https://github.com/LemmyNet/lemmy/blob/main/config/config.hjson) for more config options). Run `chown lemmy:lemmy /etc/lemmy/ -R` to set the correct owner.
|
||||
```hjson
|
||||
{
|
||||
database: {
|
||||
# put your db-passwd from above
|
||||
password: "db-passwd"
|
||||
}
|
||||
# replace with your domain
|
||||
hostname: example.com
|
||||
bind: "127.0.0.1"
|
||||
# put a random string here (required for login token encryption)
|
||||
jwt_secret: "changeme"
|
||||
}
|
||||
```
|
||||
|
||||
Systemd unit file, so that Lemmy automatically starts and stops, logs are handled via journalctl etc. Put this file into /etc/systemd/system/lemmy.service, then run `systemctl enable lemmy` and `systemctl start lemmy`.
|
||||
```
|
||||
[Unit]
|
||||
Description=Lemmy - A link aggregator for the fediverse
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=lemmy
|
||||
ExecStart=/usr/bin/lemmy_server
|
||||
Environment=LEMMY_CONFIG_LOCATION=/etc/lemmy/lemmy.hjson
|
||||
Restart=on-failure
|
||||
|
||||
# Hardening
|
||||
ProtectSystem=yes
|
||||
PrivateTmp=true
|
||||
MemoryDenyWriteExecute=true
|
||||
NoNewPrivileges=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
If you did everything right, the Lemmy logs from `journalctl -u lemmy` should show "Starting http server at 127.0.0.1:8536". You can also run `curl localhost:8536/api/v3/site` which should give a successful response, looking like `{"site_view":null,"admins":[],"banned":[],"online":0,"version":"unknown version","my_user":null,"federated_instances":null}`.
|
||||
|
||||
### Install lemmy-ui (web frontend)
|
||||
|
||||
Install dependencies (nodejs and yarn in Ubuntu 20.04 repos are too old)
|
||||
```bash
|
||||
# https://classic.yarnpkg.com/en/docs/install/#debian-stable
|
||||
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
|
||||
# https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions
|
||||
curl -fsSL https://deb.nodesource.com/setup_12.x | sudo -E bash -
|
||||
sudo apt install nodejs yarn
|
||||
```
|
||||
|
||||
Clone the git repo, checkout the version you want (0.12.2 in this case), and compile it.
|
||||
```bash
|
||||
mkdir /var/lib/lemmy-ui
|
||||
cd /var/lib/lemmy-ui
|
||||
chown lemmy:lemmy .
|
||||
# dont compile as admin
|
||||
sudo -u lemmy bash
|
||||
git clone https://github.com/LemmyNet/lemmy-ui.git --recursive .
|
||||
git checkout 0.12.2 # replace with the version you want to install
|
||||
yarn install --pure-lockfile
|
||||
yarn build:prod
|
||||
exit
|
||||
```
|
||||
|
||||
Add another systemd unit file, this time for lemmy-ui. You need to replace example.com with your actual domain. Put the file in `/etc/systemd/system/lemmy-ui.service`, then run `systemctl enable lemmy-ui` and `systemctl start lemmy-ui`.
|
||||
```
|
||||
[Unit]
|
||||
Description=Lemmy UI - Web frontend for Lemmy
|
||||
After=lemmy.service
|
||||
Before=nginx.service
|
||||
|
||||
[Service]
|
||||
User=lemmy
|
||||
WorkingDirectory=/var/lib/lemmy-ui
|
||||
ExecStart=/usr/bin/node dist/js/server.js
|
||||
Environment=LEMMY_INTERNAL_HOST=localhost:8536
|
||||
Environment=LEMMY_EXTERNAL_HOST=example.com
|
||||
Environment=LEMMY_HTTPS=true
|
||||
Restart=on-failure
|
||||
|
||||
# Hardening
|
||||
ProtectSystem=full
|
||||
PrivateTmp=true
|
||||
NoNewPrivileges=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
If everything went right, the command `curl -I localhost:1234` should show `200 OK` at the top.
|
||||
|
||||
### Configure reverse proxy and TLS
|
||||
|
||||
Install dependencies
|
||||
```bash
|
||||
apt install nginx certbot python3-certbot-nginx
|
||||
```
|
||||
|
||||
Request Let's Encrypt TLS certificate (just follow the instructions)
|
||||
```bash
|
||||
certbot certonly --nginx
|
||||
```
|
||||
|
||||
Let's Encrypt certificates should be renewed automatically, so add the line below to your crontab, by running `sudo crontab -e`. Replace example.com with your actual domain.
|
||||
```
|
||||
@daily certbot certonly --nginx --cert-name example.com -d example.com --deploy-hook 'nginx -s reload'
|
||||
```
|
||||
|
||||
Finally, add the nginx config. After downloading, you need to replace some variables in the file.
|
||||
```bash
|
||||
curl https://raw.githubusercontent.com/LemmyNet/lemmy-ansible/main/templates/nginx.conf \
|
||||
--output /etc/nginx/sites-enabled/lemmy.conf
|
||||
# put your actual domain instead of example.com
|
||||
sed -i -e 's/{{domain}}/example.com/g' /etc/nginx/sites-enabled/lemmy.conf
|
||||
sed -i -e 's/{{lemmy_port}}/8536/g' /etc/nginx/sites-enabled/lemmy.conf
|
||||
sed -i -e 's/{{lemmy_ui_port}}/1234/g' /etc/nginx/sites-enabled/lemmy.conf
|
||||
nginx -s reload
|
||||
```
|
||||
|
||||
Now open your Lemmy domain in the browser, and it should show you a configuration screen. Use it to create the first admin user and the default community.
|
||||
|
||||
### Pict-rs (for image hosting, optional)
|
||||
|
||||
Pict-rs requires a newer Rust version than the one available in Ubuntu 20.04 repos. So you need to install [Rustup](https://rustup.rs/) which installs the toolchain for you.
|
||||
|
||||
```bash
|
||||
apt install ffmpeg exiftool libgexiv2-dev --no-install-recommends
|
||||
adduser pictrs --system --disabled-login --no-create-home --group
|
||||
mkdir /var/lib/pictrs-source
|
||||
cd /var/lib/pictrs
|
||||
git clone https://git.asonix.dog/asonix/pict-rs.git .
|
||||
# check docker-compose.yml for pict-rs version used by lemmy
|
||||
# https://github.com/LemmyNet/lemmy-ansible/blob/main/templates/docker-compose.yml#L40
|
||||
git checkout v0.2.6-r2
|
||||
# or simply add the bin folder to your $PATH
|
||||
$HOME/.cargo/bin/cargo build --release
|
||||
cp target/release/pict-rs /usr/bin/
|
||||
# create folder to store image data
|
||||
mkdir /var/lib/pictrs
|
||||
chown pictrs:pictrs /var/lib/pictrs
|
||||
```
|
||||
|
||||
Pict-rs requires the `magick` command which comes with Imagemagick version 7, but Ubuntu 20.04 only comes with Imagemagick 6. So you need to install that command manually, eg from the [official website](https://imagemagick.org/script/download.php#linux).
|
||||
```
|
||||
wget https://download.imagemagick.org/ImageMagick/download/binaries/magick
|
||||
# compare hash with the "message digest" on the official page linked above
|
||||
sha256sum magick
|
||||
mv magick /usr/bin/
|
||||
chmod 755 /usr/bin/magick
|
||||
```
|
||||
|
||||
Just like before, place the config below in `/etc/systemd/system/pictrs.service`, then run `systemctl enable pictrs` and `systemctl start pictrs`.
|
||||
```
|
||||
[Unit]
|
||||
Description=pict-rs - A simple image host
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=pictrs
|
||||
ExecStart=/usr/bin/pict-rs
|
||||
Environment=PICTRS_PATH=/var/lib/pictrs
|
||||
Environment=PICTRS_ADDR=127.0.0.1:8080
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
If it is working correctly, `curl 127.0.0.1:8080` should output nothing (particularly no errors).
|
||||
|
||||
Now add the line `pictrs_url: "http://127.0.0.1:8080"` to `/etc/lemmy/lemmy.hjson` so that Lemmy knows how to reach Pict-rs. Then restart Lemmy with `systemctl restart lemmy`, and image uploads should be working.
|
||||
|
||||
## Upgrading
|
||||
|
||||
### Lemmy
|
||||
|
||||
```bash
|
||||
# installs latest release, you can also specify one with --version
|
||||
cargo install lemmy_server --target-dir /usr/bin/
|
||||
systemctl restart lemmy
|
||||
```
|
||||
|
||||
### Lemmy UI
|
||||
|
||||
```bash
|
||||
cd /var/lib/lemmy-ui
|
||||
sudo -u lemmy
|
||||
git checkout main
|
||||
git pull --tags
|
||||
git checkout 0.12.2 # replace with the version you want to install
|
||||
git submodule update
|
||||
yarn install --pure-lockfile
|
||||
yarn build:prod
|
||||
exit
|
||||
systemctl restart lemmy-ui
|
||||
```
|
||||
|
||||
### Pict-rs
|
||||
|
||||
```bash
|
||||
rustup update
|
||||
cd /var/lib/pictrs-source
|
||||
git checkout main
|
||||
git pull --tags
|
||||
# check docker-compose.yml for pict-rs version used by lemmy
|
||||
# https://github.com/LemmyNet/lemmy-ansible/blob/main/templates/docker-compose.yml#L40
|
||||
git checkout v0.2.6-r2
|
||||
# or simply add the bin folder to your $PATH
|
||||
$HOME/.cargo/bin/cargo build --release
|
||||
cp target/release/pict-rs /usr/bin/
|
||||
systemctl restart pictrs
|
||||
```
|
3
src/id/administration/install_ansible.md
Normal file
3
src/id/administration/install_ansible.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Ansible Installation
|
||||
|
||||
Follow the instructions on the [Lemmy-Ansible](https://github.com/LemmyNet/lemmy-ansible) repo.
|
54
src/id/administration/install_docker.md
Normal file
54
src/id/administration/install_docker.md
Normal file
|
@ -0,0 +1,54 @@
|
|||
# Docker Installation
|
||||
|
||||
Make sure you have both docker and docker-compose(>=`1.24.0`) installed. On Ubuntu, just run `apt install docker-compose docker.io`. Next,
|
||||
|
||||
```bash
|
||||
# create a folder for the lemmy files. the location doesnt matter, you can put this anywhere you want
|
||||
mkdir /lemmy
|
||||
cd /lemmy
|
||||
|
||||
# download default config files
|
||||
wget https://raw.githubusercontent.com/LemmyNet/lemmy/main/docker/prod/docker-compose.yml
|
||||
wget https://raw.githubusercontent.com/LemmyNet/lemmy/main/docker/lemmy.hjson
|
||||
|
||||
# Set correct permissions for pictrs folder
|
||||
mkdir -p volumes/pictrs
|
||||
sudo chown -R 991:991 volumes/pictrs
|
||||
```
|
||||
|
||||
Open up your `docker-compose.yml`, and make sure `LEMMY_EXTERNAL_HOST` for `lemmy-ui` is set to your correct host.
|
||||
|
||||
```
|
||||
- LEMMY_INTERNAL_HOST=lemmy:8536
|
||||
- LEMMY_EXTERNAL_HOST=your-domain.com
|
||||
- LEMMY_HTTPS=false
|
||||
```
|
||||
|
||||
If you'd like a different database password, you should also change it in the `docker-compose.yml` **before** your first run.
|
||||
|
||||
After this, have a look at the [config file](configuration.md) named `lemmy.hjson`, and adjust it, in particular the hostname, and possibly the db password. Then run:
|
||||
|
||||
`docker-compose up -d`
|
||||
|
||||
You can access the lemmy-ui at `http://localhost:1235`
|
||||
|
||||
To make Lemmy available outside the server, you need to setup a reverse proxy, like Nginx. [A sample nginx config](https://github.com/LemmyNet/lemmy-ansible/blob/main/templates/nginx.conf), could be setup with:
|
||||
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/LemmyNet/lemmy-ansible/main/templates/nginx.conf
|
||||
# Replace the {{ vars }}
|
||||
# The default lemmy_port is 8536
|
||||
# The default lemmy_ui_port is 1235
|
||||
sudo mv nginx.conf /etc/nginx/sites-enabled/lemmy.conf
|
||||
```
|
||||
|
||||
You will also need to setup TLS, for example with [Let's Encrypt](https://letsencrypt.org/). After this you need to restart Nginx to reload the config.
|
||||
|
||||
## Updating
|
||||
|
||||
To update to the newest version, you can manually change the version in `docker-compose.yml`. Alternatively, fetch the latest version from our git repo:
|
||||
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/LemmyNet/lemmy/main/docker/prod/docker-compose.yml
|
||||
docker-compose up -d
|
||||
```
|
53
src/id/administration/on_aws.md
Normal file
53
src/id/administration/on_aws.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
# Installing on AWS
|
||||
|
||||
> ⚠️ **Disclaimer:** this installation method is not recommended by the Lemmy developers. If you have any problems, you need to solve them yourself or ask the respective authors. If you notice any Lemmy bugs on an instance installed like this, please mention it in the bug report.
|
||||
|
||||
## Lemmy AWS CDK
|
||||
|
||||
This contains the necessary infrastructure definitions to deploy [Lemmy](https://github.com/LemmyNet/lemmy)
|
||||
to AWS using their [Cloud Development Kit](https://docs.aws.amazon.com/cdk/latest/guide/home.html).
|
||||
|
||||
### Included:
|
||||
|
||||
* ECS fargate cluster
|
||||
* Lemmy-UI
|
||||
* Lemmy
|
||||
* Pictrs
|
||||
* CloudFront CDN
|
||||
* EFS storage for image uploads
|
||||
* Aurora Serverless Postgres DB
|
||||
* Bastion VPC host
|
||||
* Load balancers for Lemmy
|
||||
* DNS records for your site
|
||||
|
||||
## Quickstart
|
||||
|
||||
Clone the [Lemmy-CDK]( https://github.com/jetbridge/lemmy-cdk).
|
||||
|
||||
Clone [Lemmy](https://github.com/LemmyNet/lemmy) and [Lemmy-UI](https://github.com/LemmyNet/lemmy-ui) to the directory above this.
|
||||
|
||||
```shell
|
||||
cp example.env.local .env.local
|
||||
# edit .env.local
|
||||
```
|
||||
|
||||
You should edit .env.local with your site settings.
|
||||
|
||||
```shell
|
||||
npm install -g aws-cdk
|
||||
npm install
|
||||
cdk bootstrap
|
||||
cdk deploy
|
||||
```
|
||||
|
||||
## Cost
|
||||
This is *not* the cheapest way to run Lemmy. The Serverless Aurora DB can run you ~$90/mo if it doesn't go to sleep.
|
||||
|
||||
## Useful CDK commands
|
||||
|
||||
* `npm run build` compile typescript to js
|
||||
* `npm run watch` watch for changes and compile
|
||||
* `npm run test` perform the jest unit tests
|
||||
* `cdk deploy` deploy this stack to your default AWS account/region
|
||||
* `cdk diff` compare deployed stack with current state
|
||||
* `cdk synth` emits the synthesized CloudFormation template
|
64
src/id/administration/troubleshooting.md
Normal file
64
src/id/administration/troubleshooting.md
Normal file
|
@ -0,0 +1,64 @@
|
|||
# Troubleshooting
|
||||
|
||||
Different problems that can occur on a new instance, and how to solve them.
|
||||
|
||||
Many Lemmy features depend on a correct reverse proxy configuration. Make sure yours is equivalent to our [nginx config](https://github.com/LemmyNet/lemmy/blob/main/ansible/templates/nginx.conf).
|
||||
|
||||
## General
|
||||
|
||||
### Logs
|
||||
|
||||
For frontend issues, check the [browser console](https://webmasters.stackexchange.com/a/77337) for any error messages.
|
||||
|
||||
For server logs, run `docker-compose logs -f lemmy` in your installation folder. You can also do `docker-compose logs -f lemmy lemmy-ui pictrs` to get logs from different services.
|
||||
|
||||
If that doesn't give enough info, try changing the line `RUST_LOG=error` in `docker-compose.yml` to `RUST_LOG=info` or `RUST_LOG=verbose`, then do `docker-compose restart lemmy`.
|
||||
|
||||
### Creating admin user doesn't work
|
||||
|
||||
Make sure that websocket is working correctly, by checking the browser console for errors. In nginx, the following headers are important for this:
|
||||
|
||||
```
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
```
|
||||
|
||||
### Rate limit error when many users access the site
|
||||
|
||||
Check that the headers `X-Real-IP` and `X-Forwarded-For` are sent to Lemmy by the reverse proxy. Otherwise, it will count all actions towards the rate limit of the reverse proxy's IP. In nginx it should look like this:
|
||||
|
||||
```
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
```
|
||||
|
||||
## Federation
|
||||
|
||||
### Other instances can't fetch local objects (community, post, etc)
|
||||
|
||||
Your reverse proxy (eg nginx) needs to forward requests with header `Accept: application/activity+json` to the backend. This is handled by the following lines:
|
||||
```
|
||||
set $proxpass "http://0.0.0.0:{{ lemmy_ui_port }}";
|
||||
if ($http_accept = "application/activity+json") {
|
||||
set $proxpass "http://0.0.0.0:{{ lemmy_port }}";
|
||||
}
|
||||
if ($http_accept = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") {
|
||||
set $proxpass "http://0.0.0.0:{{ lemmy_port }}";
|
||||
}
|
||||
proxy_pass $proxpass;
|
||||
```
|
||||
|
||||
You can test that it works correctly by running the following commands, all of them should return valid JSON:
|
||||
```
|
||||
curl -H "Accept: application/activity+json" https://your-instance.com/u/some-local-user
|
||||
curl -H "Accept: application/activity+json" https://your-instance.com/c/some-local-community
|
||||
curl -H "Accept: application/activity+json" https://your-instance.com/post/123 # the id of a local post
|
||||
curl -H "Accept: application/activity+json" https://your-instance.com/comment/123 # the id of a local comment
|
||||
```
|
||||
### Fetching remote objects works, but posting/commenting in remote communities fails
|
||||
|
||||
Check that [federation is allowed on both instances](../federation/administration.md#instance-allowlist-and-blocklist).
|
||||
|
||||
Also ensure that the time is accurately set on your server. Activities are signed with a timestamp, and will be discarded if it is off by more than 10 seconds.
|
5
src/id/client_development/client_development.md
Normal file
5
src/id/client_development/client_development.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Pengembangan Klien
|
||||
|
||||
- [Dokumen API](/api)
|
||||
- [Ekstra API HTTP](http_api_extras.md)
|
||||
- [Panduan Membuat Tema](theming.md)
|
66
src/id/client_development/custom_frontend.md
Normal file
66
src/id/client_development/custom_frontend.md
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Creating a Custom Frontend
|
||||
|
||||
The backend and frontend are completely decoupled, and run in independent Docker containers. They only communicate over the [Lemmy API](api_reference.md), which makes it quite easy to write alternative frontends.
|
||||
|
||||
This creates a lot of potential for custom frontends, which could change much of the design and user experience of Lemmy. For example, it would be possible to create a frontend in the style of a traditional forum like [phpBB](https://www.phpbb.com/), or a question-and-answer site like [stackoverflow](https://stackoverflow.com/). All without having to think about database queries, authentification or ActivityPub, which you essentially get for free.
|
||||
|
||||
## Development
|
||||
|
||||
You can use any language to create a custom frontend. The easiest option would be forking our [official frontend](https://github.com/LemmyNet/lemmy-ui), [lemmy-lite](https://github.com/IronOxidizer/lemmy-lite), or the [lemmy-frontend-example](https://github.com/LemmyNet/lemmy-front-end-example). In any case, the principle is the same: bind to `LEMMY_EXTERNAL_HOST` (default: `localhost:8536`) and handle requests using the Lemmy API at `LEMMY_INTERNAL_HOST` (default: `lemmy:8536`). Also use `LEMMY_HTTPS` to generate links with the correct protocol.
|
||||
|
||||
The next step is building a Docker image from your frontend. If you forked an existing project, it should already include a `Dockerfile` and instructions to build it. Otherwise, try searching for your language on [dockerhub](https://hub.docker.com/), official images usually have build instructions in their readme. Build a Docker image with a tag, then look for the following section in `docker/dev/docker-compose.yml`:
|
||||
|
||||
```
|
||||
lemmy-ui:
|
||||
image: dessalines/lemmy-ui:v0.8.10
|
||||
ports:
|
||||
- "1235:1234"
|
||||
restart: always
|
||||
environment:
|
||||
- LEMMY_INTERNAL_HOST=lemmy:8536
|
||||
- LEMMY_EXTERNAL_HOST=localhost:8536
|
||||
- LEMMY_HTTPS=false
|
||||
depends_on:
|
||||
- lemmy
|
||||
```
|
||||
|
||||
All you need to do is replace the value for `image` with the tag of your own Docker image (and possibly the environment variables if you need different ones). Then run `./docker_update.sh`, and after compilation, your frontend will be available on `http://localhost:1235`. You can also make the same change to `docker/federation/docker-compose.yml` and run `./start-local-instances.bash` to test federation with your frontend.
|
||||
|
||||
## Deploy with Docker
|
||||
|
||||
After building the Docker image, you need to push it to a Docker registry (such as [dockerhub](https://hub.docker.com/)). Then update the `docker-compose.yml` on your server, replacing the `image` for `lemmy-ui`, just as described above. Run `docker-compose.yml`, and after a short wait, your instance will use the new frontend.
|
||||
|
||||
Note, if your instance is deployed with Ansible, it will override `docker-compose.yml` with every run, reverting back to the default frontend. In that case you should copy the `ansible/` folder from this project to your own repository, and adjust `docker-compose.yml` directly in the repo.
|
||||
|
||||
It is also possible to use multiple frontends for the same Lemmy instance, either using subdomains or subfolders. To do that, don't edit the `lemmy-ui` section in `docker-compose.yml`, but duplicate it, adjusting the name, image and port so they are distinct for each. Then edit your nginx config to pass requests to the appropriate frontend, depending on the subdomain or path.
|
||||
|
||||
## Translations
|
||||
|
||||
You can add the [lemmy-translations](https://github.com/LemmyNet/lemmy-translations) repository to your project as a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). That way you can take advantage of same translations used in the official frontend, and you will also receive new translations contributed via weblate.
|
||||
|
||||
## Rate limiting
|
||||
|
||||
Lemmy does rate limiting for many actions based on the client IP. But if you make any API calls on the server side (eg in the case of server-side rendering, or javascript pre-rendering), Lemmy will take the IP of the Docker container. Meaning that all requests come from the same IP, and get rate limited much earlier. To avoid this problem, you need to pass the headers `X-REAL-IP` and `X-FORWARDED-FOR` on to Lemmy (the headers are set by our nginx config).
|
||||
|
||||
Here is an example snipped for NodeJS:
|
||||
|
||||
```javascript
|
||||
function setForwardedHeaders(
|
||||
headers: IncomingHttpHeaders
|
||||
): { [key: string]: string } {
|
||||
let out = {
|
||||
host: headers.host,
|
||||
};
|
||||
if (headers['x-real-ip']) {
|
||||
out['x-real-ip'] = headers['x-real-ip'];
|
||||
}
|
||||
if (headers['x-forwarded-for']) {
|
||||
out['x-forwarded-for'] = headers['x-forwarded-for'];
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
let headers = setForwardedHeaders(req.headers);
|
||||
let client = new LemmyHttp(httpUri, headers);
|
||||
```
|
82
src/id/client_development/http_api_extras.md
Normal file
82
src/id/client_development/http_api_extras.md
Normal file
|
@ -0,0 +1,82 @@
|
|||
# Lemmy HTTP API Extras
|
||||
|
||||
This contains extras not in the [API docs](/api).
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Curl Examples](#curl-examples)
|
||||
- [HTTP API exclusive features](#http-api-exclusive-features)
|
||||
* [RSS/Atom feeds](#rssatom-feeds)
|
||||
* [Images](#images)
|
||||
+ [Create (request)](#create-request)
|
||||
+ [Create (response)](#create-response)
|
||||
+ [Delete](#delete)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Curl Examples
|
||||
|
||||
**GET example**
|
||||
|
||||
```
|
||||
curl "http://localhost:8536/api/v2/community/list?sort=Hot"`
|
||||
```
|
||||
|
||||
**POST example**
|
||||
|
||||
```
|
||||
curl -i -H \
|
||||
"Content-Type: application/json" \
|
||||
-X POST \
|
||||
-d '{
|
||||
"comment_id": 374,
|
||||
"score": 1,
|
||||
"auth": eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MiwiaXNzIjoidGVzdC5sZW1teS5tbCJ9.P77RX_kpz1a_geY5eCp29sl_5mAm-k27Cwnk8JcIZJk
|
||||
}' \
|
||||
http://localhost:8536/api/v2/comment/like
|
||||
```
|
||||
|
||||
## HTTP API exclusive features
|
||||
|
||||
These features cannot be accessed from the WebSocket API:
|
||||
|
||||
- [RSS/Atom feeds](#rss-atom-feeds)
|
||||
- [Images](#images)
|
||||
|
||||
### RSS/Atom feeds
|
||||
|
||||
- All - `/feeds/all.xml?sort=Hot`
|
||||
- Community - `/feeds/c/community-name.xml?sort=Hot`
|
||||
- User - `/feeds/u/user-name.xml?sort=Hot`
|
||||
|
||||
### Images
|
||||
|
||||
Lemmy forwards image requests to a locally running Pictrs.
|
||||
|
||||
`GET /pictrs/image/{filename}?format={webp, jpg, ...}&thumbnail={96}`
|
||||
|
||||
*Format and thumbnail are optional.*
|
||||
|
||||
#### Create (request)
|
||||
|
||||
Uploaded content must be valid multipart/form-data with an image array located within the images[] key.
|
||||
|
||||
`POST /pictrs/image`
|
||||
|
||||
#### Create (response)
|
||||
|
||||
```
|
||||
{
|
||||
"files": [
|
||||
{
|
||||
"delete_token": "{token}",
|
||||
"file": "{file}.jpg"
|
||||
}
|
||||
],
|
||||
"msg": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete
|
||||
|
||||
`GET /pictrs/image/delete/{delete_token}/{file}`
|
19
src/id/client_development/theming.md
Normal file
19
src/id/client_development/theming.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Theming Guide
|
||||
|
||||
Lemmy uses [Bootstrap v4](https://getbootstrap.com/), and very few custom css classes, so any bootstrap v4 compatible theme should work fine.
|
||||
|
||||
## Creating
|
||||
|
||||
- Use a tool like [bootstrap.build](https://bootstrap.build/) to create a bootstrap v4 theme. Export the `bootstrap.min.css` once you're done, and save the `_variables.scss` too.
|
||||
|
||||
## Testing
|
||||
|
||||
- To test out a theme, you can either use your browser's web tools, or a plugin like stylus to copy-paste a theme, when viewing Lemmy.
|
||||
|
||||
## Adding
|
||||
|
||||
1. Fork the [lemmy-ui](https://github.com/LemmyNet/lemmy-ui).
|
||||
1. Copy `{my-theme-name}.min.css` to `src/assets/css/themes`. (You can also copy the `_variables.scss` here if you want).
|
||||
1. Go to `src/shared/utils.ts` and add `{my-theme-name}` to the themes list.
|
||||
1. Test locally
|
||||
1. Do a pull request with those changes.
|
35
src/id/code_of_conduct.md
Normal file
35
src/id/code_of_conduct.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Kode Etik
|
||||
|
||||
- Kami berkomitmen untuk menyediakan lingkungan yang ramah dan aman bagi semua orang, tanpa memandang tingkat pengalaman, identitas dan ekspresi gender, orientasi seksual, kecacatan, penampilan pribadi, ukuran tubuh, ras, etnis, usia, agama, kebangsaan, atau lainnya yang serupa.
|
||||
- Harap hindari menggunakan alias seksual atau nama panggilan lain yang dapat mengganggu lingkungan yang ramah dan aman bagi semua orang.
|
||||
- Harap bersikap baik dan sopan. Tidak perlu jahat atau kasar.
|
||||
- Hormati bahwa setiap orang memiliki pendapat yang berbeda dan bahwa setiap pilihan desain atau implementasi membawa timbal baliknya masing-masing. Jarang ada jawaban yang benar.
|
||||
- Harap pertahankan kritik yang tidak terstruktur seminimal mungkin. Jika Anda memiliki ide kuat yang ingin Anda coba, buat turunan (fork) dan lihat cara kerjanya.
|
||||
- Kami akan mengecualikan Anda dari interaksi jika Anda menghina, merendahkan, atau melecehkan siapa pun. Itu bukan perilaku yang disambut baik. Kami menafsirkan istilah "pelecehan" yang berada di definisi [Citizen Code of Conduct](https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md); jika Anda memiliki ketidakjelasan tentang apa yang mungkin termasuk dalam konsep itu, silakan baca definisi tersebut. Secara khusus, kami tidak menoleransi perilaku yang mengecualikan orang-orang dalam kelompok yang terpinggirkan secara sosial.
|
||||
- Pelecehan pribadi juga tidak dapat diterima. Tidak peduli siapa Anda, jika Anda merasa telah atau sedang dilecehkan atau dibuat tidak nyaman oleh anggota komunitas, harap hubungi salah satu ops saluran atau tim moderasi Lemmy segera. Baik Anda kontributor tetap atau pendatang baru, kami peduli untuk menjadikan komunitas ini tempat yang aman bagi Anda dan kami mendukung Anda.
|
||||
- Demikian juga segala perilaku spam, troll, memicu, memancing, atau mencuri perhatian lainnya tidak diperbolehkan.
|
||||
|
||||
[**Kirim Pesan ke Tim Moderasi di Mastodon**](https://mastodon.social/@LemmyDev)
|
||||
|
||||
[**Kirim Surel ke Tim Moderasi**](mailto:contact@lemmy.ml)
|
||||
|
||||
## Moderasi
|
||||
|
||||
Ini merupakan kebijakan untuk menegakkan kode etik komunitas. Jika Anda rasa sebuah utas memerlukan moderasi, mohon hubungi tim moderasi Lemmy.
|
||||
|
||||
1. Konten yang melanggar kode etik Lemmy, termasuk konten yang penuh kebencian, menyakitkan, menindas, atau eksklusifitas, tidak diperbolehkan (Mengutuk diperbolehkan, tetapi tidak menargetkan pengguna lain dan tidak dengan cara yang penuh kebencian).
|
||||
2. Konten yang dianggap tidak pantas oleh moderator, baik yang tercantum dalam kode etik atau tidak, juga tidak diperbolehkan.
|
||||
3. Moderator pertama-tama akan menanggapi konten tersebut dengan peringatan, pada saat yang sama konten yang menyinggung kemungkinan akan dihapus bila memungkinkan.
|
||||
4. Jika peringatan tersebut tidak diindahkan, pengguna akan “ditendang”, yaitu dikeluarkan dari saluran komunikasi untuk menenangkan diri.
|
||||
5. Jika pengguna kembali dan terus membuat masalah, mereka akan dilarang, yaitu dikecualikan tanpa batas waktu.
|
||||
6. Moderator dapat memilih atas pilihan mereka untuk membatalkan larangan pengguna jika itu adalah pelanggaran pertama dan mereka menawarkan pihak yang tersinggung permintaan maaf yang tulus.
|
||||
7. Jika seorang moderator melarang seseorang dan menurut Anda itu tidak dibenarkan, silakan bicarakan dengan moderator itu, atau dengan moderator lain, secara pribadi. Keluhan tentang larangan dalam saluran tidak diperbolehkan.
|
||||
8. Moderator memiliki standar yang lebih tinggi daripada anggota komunitas lainnya. Jika seorang moderator membuat situasi yang tidak pantas, mereka seharusnya mengharapkan lebih sedikit kelonggaran daripada yang lain.
|
||||
|
||||
Di komunitas Lemmy, kami berusaha untuk mengambil langkah ekstra untuk saling menjaga satu sama lain. Jangan hanya bertujuan untuk secara teknis tidak dapat ditembus, cobalah untuk menjadi diri Anda yang terbaik. Secara khusus, hindari berhubungan dengan masalah yang menyinggung atau sensitif, terutama jika itu di luar topik; ini terlalu sering menyebabkan pertengkaran yang tidak perlu, perasaan terluka, dan kepercayaan yang rusak; lebih buruk, itu dapat membuat orang menjauh dari komunitas sepenuhnya.
|
||||
|
||||
Dan jika seseorang mempermasalahkan sesuatu yang Anda katakan atau lakukan, tahan keinginan untuk bersikap defensif. Berhentilah melakukan apa yang mereka keluhkan dan minta maaf. Bahkan jika Anda merasa telah disalahtafsirkan atau dituduh secara tidak adil, kemungkinan besar ada sesuatu yang dapat Anda komunikasikan dengan lebih baik — ingatlah bahwa adalah tanggung jawab Anda untuk membuat orang lain nyaman. Semua orang ingin bersahabat dan kami semua di sini pertama dan terutama karena kami ingin berbicara tentang teknologi keren. Anda akan menemukan bahwa orang akan bersemangat untuk mengambil niat baik dan memaafkan selama Anda mendapatkan kepercayaan mereka.
|
||||
|
||||
Kebijakan penegakan yang tercantum di atas berlaku untuk semua tempat resmi Lemmy; termasuk repositori git di bawah [github.com/LemmyNet](https://github.com/LemmyNet) dan [yerbamate.ml/LemmyNet](https://yerbamate.ml/LemmyNet), [saluran Matrix](https://matrix.to/#/!BZVTUuEiNmRcbFeLeI:matrix.org), [lemmy.ml](https://lemmy.ml), dan peladen lain di bawah domain itu. Untuk proyek lain yang mengadopsi Kode Etik Lemmy, silakan hubungi pengelola proyek tersebut untuk penegakan. Jika Anda ingin menggunakan kode etik ini untuk proyek Anda sendiri, pertimbangkan untuk menyebutkan secara eksplisit kebijakan moderasi Anda atau membuat salinan dengan kebijakan moderasi Anda sendiri untuk menghindari kebingungan.
|
||||
|
||||
Diadaptasi dari [Kode Etik Rust](https://www.rust-lang.org/policies/code-of-conduct), yang dimana berdasarkan pada [Kebijakan terhadap Troll Node.js](http://blog.izs.me/post/30036893703/policy-on-trolling) dan juga [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).
|
40
src/id/contributing/contributing.md
Normal file
40
src/id/contributing/contributing.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Berkontribusi
|
||||
|
||||
Informasi tentang berkontribusi ke Lemmy, entah itu penerjemahan, menguji, pendesainan, atau pemrograman.
|
||||
|
||||
## Pelacak Isu/Repositori
|
||||
|
||||
- [GitHub (untuk isu dan permintaan dorong (pull request))](https://github.com/LemmyNet/lemmy)
|
||||
- [Gitea (hanya untuk permintaan dorong)](https://yerbamate.ml/LemmyNet/lemmy)
|
||||
- [Codeberg](https://codeberg.org/LemmyNet/lemmy)
|
||||
|
||||
## Penerjemahan
|
||||
|
||||
Periksa [Weblate Lemmy](https://weblate.yerbamate.ml/projects/lemmy/) untuk penerjemahan. Anda bisa juga membantu dengan [menerjemahkan dokumentasi ini](https://github.com/LemmyNet/lemmy-docs#adding-a-new-language).
|
||||
|
||||
|
||||
## Arsitektur
|
||||
|
||||
### Antarmuka
|
||||
|
||||
- Antarmuka ditulis dengan `Typescript`, menggunakan kerangka mirip-React yang dikenal sebagai [Inferno](https://infernojs.org/). Semua elemen antarmuka merupakan komponen `.tsx` yang dapat digunakan ulang.
|
||||
- Repositori antarmuka adalah [lemmy-ui](https://github.com/LemmyNet/lemmy-ui).
|
||||
- Rutenya adalah `src/shared/routes.ts`.
|
||||
- Komponen berada di `src/shared/components`.
|
||||
|
||||
### Bagian-Belakang
|
||||
|
||||
- Bagian-belakang dengan `Rust`, menggunakan `Diesel` dan `Actix`.
|
||||
- Kode peladen dibagi ke bagian utama di `src`. Mereka termasuk:
|
||||
- `db` - Aksi basis data tingkat rendah.
|
||||
- Penambahan basis data dilakukan menggunakan migrasi Diesel. Jalankan `diesel migration generate xxxxx` untuk menambahkan sesuatu yang baru.
|
||||
- `api` - Interaksi pengguna tingkat tinggi (hal seperti `CreateComment`)
|
||||
- `routes` - Endpoint peladen.
|
||||
- `apub` - Konversi activitypub.
|
||||
- `websocket` - Membuat peladen websocket.
|
||||
|
||||
## Linting / Formatting
|
||||
|
||||
- Every front and back end commit is automatically formatted then linted using `husky`, and `lint-staged`.
|
||||
- Rust with `cargo fmt` and `cargo clippy`.
|
||||
- Typescript with `prettier` and `eslint`.
|
40
src/id/contributing/docker_development.md
Normal file
40
src/id/contributing/docker_development.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Pengembangan Docker
|
||||
|
||||
## Dependensi
|
||||
### Distro berbasis Debian
|
||||
|
||||
```bash
|
||||
sudo apt install git docker-compose
|
||||
sudo systemctl start docker
|
||||
git clone https://github.com/LemmyNet/lemmy
|
||||
```
|
||||
|
||||
### Distro berbasis Arch
|
||||
|
||||
```bash
|
||||
sudo pacman -S git docker-compose
|
||||
sudo systemctl start docker
|
||||
git clone https://github.com/LemmyNet/lemmy
|
||||
```
|
||||
|
||||
## Jalankan
|
||||
|
||||
```bash
|
||||
cd docker/dev
|
||||
./docker_update.sh
|
||||
```
|
||||
|
||||
dan pergi ke http://localhost:1236
|
||||
|
||||
*Catatan: banyak fitur (seperti dokumen dan gambar) tidak akan berfungsi tanpa menggunakan profil nginx seperti itu di `ansible/templates/nginx.conf`.
|
||||
|
||||
Untuk mempercepat pengompilasian Docker, tambahkan yang di bawah ini ke `/etc/docker/daemon.json` dan mulai ulang Docker.
|
||||
```
|
||||
{
|
||||
"features": {
|
||||
"buildkit": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Jika penyusunan masih lambat, sebaiknya Anda gunakan [penyusunan lokal](local_development.md).
|
60
src/id/contributing/federation_development.md
Normal file
60
src/id/contributing/federation_development.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Federation Development
|
||||
|
||||
## Running locally
|
||||
|
||||
Install the dependencies as described in [Docker development](docker_development.md). Then run the following
|
||||
|
||||
```bash
|
||||
cd docker/federation
|
||||
./start-local-instances.bash
|
||||
```
|
||||
|
||||
The federation test sets up 5 instances:
|
||||
|
||||
Instance | Username | Location | Notes
|
||||
--- | --- | --- | ---
|
||||
lemmy-alpha | lemmy_alpha | [127.0.0.1:8540](http://127.0.0.1:8540) | federated with all other instances
|
||||
lemmy-beta | lemmy_beta | [127.0.0.1:8550](http://127.0.0.1:8550) | federated with all other instances
|
||||
lemmy-gamma | lemmy_gamma | [127.0.0.1:8560](http://127.0.0.1:8560) | federated with all other instances
|
||||
lemmy-delta | lemmy_delta | [127.0.0.1:8570](http://127.0.0.1:8570) | only allows federation with lemmy-beta
|
||||
lemmy-epsilon | lemmy_epsilon | [127.0.0.1:8580](http://127.0.0.1:8580) | uses blocklist, has lemmy-alpha blocked
|
||||
|
||||
You can log into each using the instance name, and `lemmy` as the password, IE (`lemmy_alpha`, `lemmy`).
|
||||
|
||||
To start federation between instances, visit one of them and search for a user, community or post, like this. Note that
|
||||
the Lemmy backend runs on a different port than the frontend, so you have to increment the port number from
|
||||
the URL bar by one.
|
||||
- `!main@lemmy-alpha:8541`
|
||||
- `http://lemmy-beta:8551/post/3`
|
||||
- `@lemmy-gamma@lemmy-gamma:8561`
|
||||
|
||||
Firefox containers are a good way to test them interacting.
|
||||
|
||||
## Running on a server
|
||||
|
||||
Note that federation is currently in alpha. **Only use it for testing**, not on any production server, and be aware that turning on federation may break your instance.
|
||||
|
||||
Follow the normal installation instructions, either with [Ansible](../administration/install_ansible.md) or
|
||||
[manually](../administration/install_docker.md). Then replace the line `image: dessalines/lemmy:v0.x.x` in
|
||||
`/lemmy/docker-compose.yml` with `image: dessalines/lemmy:federation`. Add and configure [this federation block](https://github.com/lemmynet/lemmy/blob/main/config/config.hjson#L64) to your `lemmy.hjson`.
|
||||
|
||||
Afterwards, and whenever you want to update to the latest version, run these commands on the server:
|
||||
|
||||
```
|
||||
cd /lemmy/
|
||||
sudo docker-compose pull
|
||||
sudo docker-compose up -d
|
||||
```
|
||||
|
||||
## Security Model
|
||||
|
||||
- HTTP signature verify: This ensures that activity really comes from the activity that it claims
|
||||
- check_is_apub_valid : Makes sure its in our allowed instances list
|
||||
- Lower level checks: To make sure that the user that creates/updates/removes a post is actually on the same instance as that post
|
||||
|
||||
For the last point, note that we are *not* checking whether the actor that sends the create activity for a post is
|
||||
actually identical to the post's creator, or that the user that removes a post is a mod/admin. These things are checked
|
||||
by the API code, and its the responsibility of each instance to check user permissions. This does not leave any attack
|
||||
vector, as a normal instance user cant do actions that violate the API rules. The only one who could do that is the
|
||||
admin (and the software deployed by the admin). But the admin can do anything on the instance, including send activities
|
||||
from other user accounts. So we wouldnt actually gain any security by checking mod permissions or similar.
|
102
src/id/contributing/local_development.md
Normal file
102
src/id/contributing/local_development.md
Normal file
|
@ -0,0 +1,102 @@
|
|||
# Pengembangan Lokal
|
||||
|
||||
### Pasang persyaratan penyusunan
|
||||
Pasang Rust menggunakan [opsi yang direkomendasikan di rust-lang.org](https://www.rust-lang.org/tools/install) (rustup).
|
||||
|
||||
#### Distro berbasis Debian
|
||||
```
|
||||
sudo apt install git cargo libssl-dev pkg-config libpq-dev yarn curl gnupg2 espeak
|
||||
# install yarn
|
||||
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
|
||||
sudo apt update && sudo apt install yarn
|
||||
```
|
||||
|
||||
#### Distro berbasis Arch
|
||||
```
|
||||
sudo pacman -S git cargo libssl-dev pkg-config libpq-dev yarn curl gnupg2 espeak
|
||||
# install yarn (stable)
|
||||
curl -o- -L https://yarnpkg.com/install.sh | bash
|
||||
```
|
||||
|
||||
#### macOS
|
||||
Pasang [Homebrew](https://brew.sh/) jika Anda belum memasangnya.
|
||||
|
||||
Terakhir, pasang Node dan Yarn.
|
||||
|
||||
```
|
||||
brew install node yarn
|
||||
```
|
||||
|
||||
### Dapatkan kode sumber bagian-belakang
|
||||
```
|
||||
git clone https://github.com/LemmyNet/lemmy.git
|
||||
# or alternatively from gitea
|
||||
# git clone https://yerbamate.ml/LemmyNet/lemmy.git
|
||||
```
|
||||
|
||||
### Susun bagian-belakang (Rust)
|
||||
```
|
||||
cargo build
|
||||
# for development, use `cargo check` instead)
|
||||
```
|
||||
|
||||
### Dapatkan kode sumber antarmuka
|
||||
```
|
||||
git clone https://github.com/LemmyNet/lemmy-ui.git --recurse-submodules
|
||||
```
|
||||
|
||||
### Siapkan postgresql
|
||||
#### Distro berbasis Debian
|
||||
```
|
||||
sudo apt install postgresql
|
||||
sudo systemctl start postgresql
|
||||
|
||||
# Either execute db-init.sh, or manually initialize the postgres database:
|
||||
sudo -u postgres psql -c "create user lemmy with password 'password' superuser;" -U postgres
|
||||
sudo -u postgres psql -c 'create database lemmy with owner lemmy;' -U postgres
|
||||
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
|
||||
```
|
||||
|
||||
#### Distro berbasis Arch
|
||||
```
|
||||
sudo pacman -S postgresql
|
||||
sudo systemctl start postgresql
|
||||
|
||||
# Either execute db-init.sh, or manually initialize the postgres database:
|
||||
sudo -u postgres psql -c "create user lemmy with password 'password' superuser;" -U postgres
|
||||
sudo -u postgres psql -c 'create database lemmy with owner lemmy;' -U postgres
|
||||
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
|
||||
```
|
||||
|
||||
#### macOS
|
||||
```
|
||||
brew install postgresql
|
||||
brew services start postgresql
|
||||
/usr/local/opt/postgres/bin/createuser -s postgres
|
||||
|
||||
# Either execute db-init.sh, or manually initialize the postgres database:
|
||||
psql -c "create user lemmy with password 'password' superuser;" -U postgres
|
||||
psql -c 'create database lemmy with owner lemmy;' -U postgres
|
||||
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
|
||||
```
|
||||
|
||||
### Jalankan sebuah peladen pengembangan lokal
|
||||
```
|
||||
cd lemmy
|
||||
cargo run
|
||||
```
|
||||
|
||||
Kemudian buka [localhost:1235](http://localhost:1235) di peramban Anda. Untuk memuat ulang perubahan bagian-belakang, Anda akan harus menjalankan ulang `cargo run`. Anda bisa menggunakan `cargo check` sebagai jalan cepat untuk menemukan galat penyusunan.
|
||||
|
||||
Untuk melakukan pengembangan antarmuka:
|
||||
|
||||
```
|
||||
cd lemmy-ui
|
||||
yarn
|
||||
yarn dev
|
||||
```
|
||||
|
||||
dan pergi ke [localhost:1234](http://localhost:1234). Simpanan antarmuka seharusnya menyusun ulang proyek tersebut.
|
||||
|
||||
Mohon dicatat bahwa penyiapan ini tidak termasuk pengunggahan gambar. Jika Anda ingin menguji itu, Anda harus menggunakan [pengembangan Docker](docker_development.md).
|
19
src/id/contributing/release_process.md
Normal file
19
src/id/contributing/release_process.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Branching and Releases
|
||||
|
||||
## Branches
|
||||
|
||||
In general, our handling of branches is the one described in [A stable mainline branching model for Git](https://www.bitsnbites.eu/a-stable-mainline-branching-model-for-git/). One difference is that we avoid rebase, and instead merge the base branch into the current working branch. This helps to avoid force pushes and conflicts.
|
||||
|
||||
## Releases
|
||||
|
||||
- For major release: make a new branch `release/v0.x`
|
||||
- For minor release: cherry-pick desired changes onto `release/v0.x` branch
|
||||
- Make a beta or release candidate version with `docker/prod/deploy.sh`
|
||||
- Do the same for `lemmy-ui`: `./deploy.sh 0.x.0-rc-x`
|
||||
- Deploy to federation test instances
|
||||
- Keeping one instance at the last stable version to test federation compatibility (automate this with ansible)
|
||||
- `ansible-playbook -i federation playbooks/site.yml --vault-password-file vault_pass -e rc_version=0.x.0-rc.x`
|
||||
- Test that everything works as expected, make new beta/rc releases if needed
|
||||
- Deploy to lemmy.ml, to discover remaining problems
|
||||
- If that went well, make the official `0.x.0` release with `docker/prod/deploy.sh`
|
||||
- Announce the release on Lemmy, Matrix, Mastodon
|
42
src/id/contributing/resources.md
Normal file
42
src/id/contributing/resources.md
Normal file
|
@ -0,0 +1,42 @@
|
|||
# Sumber/Pustaka
|
||||
|
||||
- [Diesel to Postgres data types](https://kotiri.com/2018/01/31/postgresql-diesel-rust-types.html)
|
||||
- [helpful diesel examples](http://siciarz.net/24-days-rust-diesel/)
|
||||
- [Recursive query for adjacency list for nested comments](https://stackoverflow.com/questions/192220/what-is-the-most-efficient-elegant-way-to-parse-a-flat-table-into-a-tree/192462#192462)
|
||||
- [SimpleMDE](https://github.com/sparksuite/simplemde-markdown-editor)
|
||||
- [Markdown-it](https://github.com/markdown-it/markdown-it)
|
||||
- [Sticky Sidebar](https://stackoverflow.com/questions/38382043/how-to-use-css-position-sticky-to-keep-a-sidebar-visible-with-bootstrap-4/49111934)
|
||||
- [RXJS websocket](https://stackoverflow.com/questions/44060315/reconnecting-a-websocket-in-angular-and-rxjs/44067972#44067972)
|
||||
- [Rust JWT](https://github.com/Keats/jsonwebtoken)
|
||||
- [Hierarchical tree building javascript](https://stackoverflow.com/a/40732240/1655478)
|
||||
- [Hot sorting discussion](https://meta.stackexchange.com/questions/11602/what-formula-should-be-used-to-determine-hot-questions) [2](https://medium.com/hacking-and-gonzo/how-reddit-ranking-algorithms-work-ef111e33d0d9)
|
||||
- [Classification types.](https://www.reddit.com/r/ModeratorDuck/wiki/subreddit_classification)
|
||||
- [RES expando - Possibly make this into a switching react component.](https://github.com/honestbleeps/Reddit-Enhancement-Suite/tree/d21f55c21e734f47d8ed03fe0ebce5b16653b0bd/lib/modules/hosts)
|
||||
- [Temp Icon](https://www.flaticon.com/free-icon/mouse_194242)
|
||||
- [Rust docker build](https://shaneutt.com/blog/rust-fast-small-docker-image-builds/)
|
||||
- [Zurb mentions](https://github.com/zurb/tribute)
|
||||
- [TippyJS](https://github.com/atomiks/tippyjs)
|
||||
- [SQL function indexes](https://sorentwo.com/2013/12/30/let-postgres-do-the-work.html)
|
||||
|
||||
# Sumber ActivityPub
|
||||
|
||||
## Dokumen Resmi
|
||||
|
||||
- [ActivityPub standard](https://www.w3.org/TR/activitypub/)
|
||||
- [Activitypub vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/)
|
||||
|
||||
## Penjelasan
|
||||
|
||||
- [ActivityPub - one protocol to rule them all?](https://schub.io/blog/2018/02/01/activitypub-one-protocol-to-rule-them-all.html)
|
||||
- [A highly opinionated guide to learning about ActivityPub](https://tinysubversions.com/notes/reading-activitypub/)
|
||||
- [Activitypub implementers guide](https://socialhub.activitypub.rocks/t/draft-guide-for-new-activitypub-implementers/479)
|
||||
- [Mastodon Blog: How to implement a basic ActivityPub server](https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/)
|
||||
- [Mastodon Blog: Implementing an ActivityPub inbox](https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/)
|
||||
- [Data storage questions](https://socialhub.activitypub.rocks/t/data-storage-questions/579)
|
||||
- [Activitypub as it has been understood](https://flak.tedunangst.com/post/ActivityPub-as-it-has-been-understood)
|
||||
|
||||
## Contoh dan Pustaka
|
||||
|
||||
- [ActivityPub example server](https://github.com/tOkeshu/activitypub-example)
|
||||
- [ActivityStreams crate](https://docs.rs/activitystreams/)
|
||||
- [HTTP Signatures crate](https://git.asonix.dog/Aardwolf/http-signature-normalization)
|
28
src/id/contributing/tests.md
Normal file
28
src/id/contributing/tests.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
### Pengujian
|
||||
|
||||
#### Rust
|
||||
|
||||
Setelah memasang [dependensi pengembangan lokal](local_development.md), jalankan perintah berikut:
|
||||
|
||||
```bash
|
||||
psql -U lemmy -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
|
||||
./test.sh
|
||||
```
|
||||
|
||||
### Federasi
|
||||
|
||||
Pasang [dependensi pengembangan lokal](local_development.md) dan tambahkan baris berikut ke `/etc/hosts`:
|
||||
|
||||
```
|
||||
127.0.0.1 lemmy-alpha
|
||||
127.0.0.1 lemmy-beta
|
||||
127.0.0.1 lemmy-gamma
|
||||
127.0.0.1 lemmy-delta
|
||||
127.0.0.1 lemmy-epsilon
|
||||
```
|
||||
|
||||
Kemudian gunakan skrip berikut untuk menjalankan pengujian:
|
||||
```
|
||||
cd api_tests
|
||||
./run-federation-test.bash
|
||||
```
|
40
src/id/federation/administration.md
Normal file
40
src/id/federation/administration.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Federation Administration
|
||||
|
||||
Note: ActivityPub federation is still under development. We recommend that you only enable it on test instances for now.
|
||||
|
||||
To enable federation, change the setting `federation.enabled` to `true` in `lemmy.hjson`, and restart Lemmy.
|
||||
|
||||
Federation does not start automatically, but needs to be triggered manually through the search. To do this you have to enter a reference to a remote object, such as:
|
||||
|
||||
- `!main@lemmy.ml` (Community)
|
||||
- `@nutomic@lemmy.ml` (User)
|
||||
- `https://lemmy.ml/c/programming` (Community)
|
||||
- `https://lemmy.ml/u/nutomic` (User)
|
||||
- `https://lemmy.ml/post/123` (Post)
|
||||
- `https://lemmy.ml/comment/321` (Comment)
|
||||
|
||||
For an overview of how federation in Lemmy works on a technical level, check out our [Federation Overview](contributing_federation_overview.md).
|
||||
|
||||
## Federation Modes
|
||||
|
||||
Through the combination of federation config options, there are a couple different federation modes, differing in their restrictiveness. For now we don't recommend to use open federation, because moderation tools are lacking and there might be security problems in the federation code. Open federation should be fine for test instances and smaller instances, but bigger instances should prefer to use a more closed federation.
|
||||
|
||||
It is important to note that these settings only affect sending and receiving of data between instances. If allow federation with a certain instance, and then remove it from the allowlist, this will not affect previously federated data. These communities, users, posts and comments will still be shown. They will just not be updated anymore. And even if an instance is blocked, it can still fetch and display public data from your instance.
|
||||
|
||||
### Using allowlist, strict_allowlist = true
|
||||
|
||||
The most strict mode. Lemmy will only federate with instances from the allowlist, and block everything else. This includes all posts, comments, votes and private messages, you will only see them if the author is on an allowed instance. This means that remote communities or threads can be incomplete, as your instance will block any posts or comments whose author is not on an allowed instance.
|
||||
|
||||
The blocklist is ignored in this mode.
|
||||
|
||||
### Using allowlist, strict_allowlist = false
|
||||
|
||||
This mode is a bit more open than the one above. For local communities, the behaviour is identical, only users from allowed instances can post, comment or vote. The difference is with remote communities. The allowlist doesn't apply to them, so you will see all posts, comments and votes in remote communities (unless the author's instance is blocked). Private messages can be sent by any remote user that isn't blocked.
|
||||
|
||||
If a blocklist is set, all communication with the blocked instances will be prevented, no matter in which context.
|
||||
|
||||
### Using only blocklist
|
||||
|
||||
If no allowlist is specified, Lemmy will federate with any instance. This is the most open mode, and potentially the most risky, as someone could create a malicious instance, and immediately send spam or other problematic content to your instance. You can use the blocklist to prevent federation with such instances one by one.
|
||||
|
||||
`strict_allowlist` is ignored in this case.
|
1
src/id/federation/federation.md
Normal file
1
src/id/federation/federation.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Federasi
|
378
src/id/federation/lemmy_protocol.md
Normal file
378
src/id/federation/lemmy_protocol.md
Normal file
|
@ -0,0 +1,378 @@
|
|||
# Lemmy Federation Protocol
|
||||
|
||||
The Lemmy Protocol (or Lemmy Federation Protocol) is a subset of the [ActivityPub Protocol](https://www.w3.org/TR/activitypub/), with some extensions.
|
||||
|
||||
This document is targeted at developers who are familiar with the ActivityPub and ActivityStreams protocols. It gives a detailed outline of the actors, objects and activities used by Lemmy.
|
||||
|
||||
Before reading this, have a look at our [Federation Overview](contributing_federation_overview.md) to get an idea how Lemmy federation works on a high level.
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Context](#context)
|
||||
- [Actors](#actors)
|
||||
* [Community](#community)
|
||||
* [User](#user)
|
||||
- [Objects](#objects)
|
||||
* [Post](#post)
|
||||
* [Comment](#comment)
|
||||
* [Private Message](#private-message)
|
||||
- [Collections](#collections)
|
||||
* [Community Outbox](#community-outbox)
|
||||
* [Community Followers](#community-followers)
|
||||
* [Community Moderators](#community-moderators)
|
||||
* [User Outbox](#user-outbox)
|
||||
- [Activities](#activities)
|
||||
* [User to Community](#user-to-community)
|
||||
+ [Follow](#follow)
|
||||
+ [Unfollow](#unfollow)
|
||||
+ [Report Post or Comment](#report-post-or-comment)
|
||||
* [Community to User](#community-to-user)
|
||||
+ [Accept Follow](#accept-follow)
|
||||
+ [Announce](#announce)
|
||||
* [Announcable](#announcable)
|
||||
+ [Create or Update Post](#create-or-update-post)
|
||||
+ [Create or Update Comment](#create-or-update-comment)
|
||||
+ [Like Post or Comment](#like-post-or-comment)
|
||||
+ [Dislike Post or Comment](#dislike-post-or-comment)
|
||||
+ [Undo Like or Dislike Post or Comment](#undo-like-or-dislike-post-or-comment)
|
||||
+ [Delete Post or Comment](#delete-post-or-comment)
|
||||
+ [Remove Post or Comment](#remove-post-or-comment)
|
||||
+ [Undo Delete or Remove](#undo-delete-or-remove)
|
||||
+ [Add Mod](#add-mod)
|
||||
+ [Remove Mod](#remove-mod)
|
||||
+ [Block User](#block-user)
|
||||
+ [Undo Block User](#undo-block-user)
|
||||
* [User to User](#user-to-user)
|
||||
+ [Create or Update Private message](#create-or-update-private-message)
|
||||
+ [Delete Private Message](#delete-private-message)
|
||||
+ [Undo Delete Private Message](#undo-delete-private-message)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Context
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/context.json}}
|
||||
```
|
||||
|
||||
The context is identical for all activities and objects.
|
||||
|
||||
## Actors
|
||||
|
||||
### Community
|
||||
|
||||
An automated actor. Users can send posts or comments to it, which the community forwards to its followers in the form of `Announce`.
|
||||
|
||||
Sends activities to user: `Accept/Follow`, `Announce`
|
||||
|
||||
Receives activities from user: `Follow`, `Undo/Follow`, `Create`, `Update`, `Like`, `Dislike`, `Remove` (only admin/mod), `Delete` (only creator), `Undo` (only for own actions)
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/objects/group.json}}
|
||||
```
|
||||
|
||||
| Field Name | Description |
|
||||
|---|---|
|
||||
| `preferredUsername` | Name of the actor |
|
||||
| `name` | Title of the community |
|
||||
| `sensitive` | True indicates that all posts in the community are nsfw |
|
||||
| `attributedTo` | First the community creator, then all the remaining moderators |
|
||||
| `content` | Text for the community sidebar, usually containing a description and rules |
|
||||
| `icon` | Icon, shown next to the community name |
|
||||
| `image` | Banner image, shown on top of the community page |
|
||||
| `inbox` | ActivityPub inbox URL |
|
||||
| `outbox` | ActivityPub outbox URL, only contains up to 20 latest posts, no comments, votes or other activities |
|
||||
| `followers` | Follower collection URL, only contains the number of followers, no references to individual followers |
|
||||
| `endpoints` | Contains URL of shared inbox |
|
||||
| `published` | Datetime when the community was first created |
|
||||
| `updated` | Datetime when the community was last changed |
|
||||
| `publicKey` | The public key used to verify signatures from this actor |
|
||||
|
||||
### User
|
||||
|
||||
A person, interacts primarily with the community where it sends and receives posts/comments. Can also create and moderate communities, and send private messages to other users.
|
||||
|
||||
Sends activities to Community: `Follow`, `Undo/Follow`, `Create`, `Update`, `Like`, `Dislike`, `Remove` (only admin/mod), `Delete` (only creator), `Undo` (only for own actions)
|
||||
|
||||
Receives activities from Community: `Accept/Follow`, `Announce`
|
||||
|
||||
Sends and receives activities from/to other users: `Create/Note`, `Update/Note`, `Delete/Note`, `Undo/Delete/Note` (all those related to private messages)
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/objects/person.json}}
|
||||
```
|
||||
|
||||
| Field Name | Description |
|
||||
|---|---|
|
||||
| `preferredUsername` | Name of the actor |
|
||||
| `name` | The user's displayname |
|
||||
| `content` | User bio |
|
||||
| `icon` | The user's avatar, shown next to the username |
|
||||
| `image` | The user's banner, shown on top of the profile |
|
||||
| `inbox` | ActivityPub inbox URL |
|
||||
| `endpoints` | Contains URL of shared inbox |
|
||||
| `published` | Datetime when the user signed up |
|
||||
| `updated` | Datetime when the user profile was last changed |
|
||||
| `publicKey` | The public key used to verify signatures from this actor |
|
||||
|
||||
The user inbox is not actually implemented yet, and is only a placeholder for ActivityPub implementations which require it.
|
||||
|
||||
## Objects
|
||||
|
||||
### Post
|
||||
|
||||
A page with title, and optional URL and text content. The URL often leads to an image, in which case a thumbnail is included. Each post belongs to exactly one community.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/objects/page.json}}
|
||||
```
|
||||
|
||||
| Field Name | Description |
|
||||
|---|---|
|
||||
| `attributedTo` | ID of the user which created this post |
|
||||
| `to` | ID of the community where it was posted to |
|
||||
| `name` | Title of the post |
|
||||
| `content` | Body of the post |
|
||||
| `url` | An arbitrary link to be shared |
|
||||
| `image` | Thumbnail for `url`, only present if it is an image link |
|
||||
| `commentsEnabled` | False indicates that the post is locked, and no comments can be added |
|
||||
| `sensitive` | True marks the post as NSFW, blurs the thumbnail and hides it from users with NSFW settign disabled |
|
||||
| `stickied` | True means that it is shown on top of the community |
|
||||
| `published` | Datetime when the post was created |
|
||||
| `updated` | Datetime when the post was edited (not present if it was never edited) |
|
||||
|
||||
### Comment
|
||||
|
||||
A reply to a post, or reply to another comment. Contains only text (including references to other users or communities). Lemmy displays comments in a tree structure.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/objects/note.json}}
|
||||
```
|
||||
|
||||
| Field Name | Description |
|
||||
|---|---|
|
||||
| `attributedTo` | ID of the user who created the comment |
|
||||
| `to` | Community where the comment was made |
|
||||
| `content` | The comment text |
|
||||
| `inReplyTo` | IDs of the post where this comment was made, and the parent comment. If this is a top-level comment, `inReplyTo` only contains the post |
|
||||
| `published` | Datetime when the comment was created |
|
||||
| `updated` | Datetime when the comment was edited (not present if it was never edited) |
|
||||
|
||||
### Private Message
|
||||
|
||||
A direct message from one user to another. Can not include additional users. Threading is not implemented yet, so the `inReplyTo` field is missing.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/objects/chat_message.json}}
|
||||
```
|
||||
|
||||
| Field Name | Description |
|
||||
|---|---|
|
||||
| `attributedTo` | ID of the user who created this private message |
|
||||
| `to` | ID of the recipient |
|
||||
| `content` | The text of the private message |
|
||||
| `published` | Datetime when the message was created |
|
||||
| `updated` | Datetime when the message was edited (not present if it was never edited) |
|
||||
|
||||
## Collections
|
||||
|
||||
### Community Outbox
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/collections/group_outbox.json}}
|
||||
```
|
||||
|
||||
The outbox only contains `Create/Post` activities for now.
|
||||
|
||||
### Community Followers
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/collections/group_followers.json}}
|
||||
```
|
||||
|
||||
The followers collection is only used to expose the number of followers. Actor IDs are not included, to protect user privacy.
|
||||
|
||||
### Community Moderators
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/collections/group_moderators.json}}
|
||||
```
|
||||
|
||||
### User Outbox
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/collections/person_outbox.json}}
|
||||
```
|
||||
|
||||
## Activities
|
||||
|
||||
### User to Community
|
||||
|
||||
#### Follow
|
||||
|
||||
When the user clicks "Subscribe" in a community, a `Follow` is sent. The community automatically responds with an `Accept/Follow`.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/following/follow.json}}
|
||||
```
|
||||
|
||||
#### Unfollow
|
||||
|
||||
Clicking on the unsubscribe button in a community causes an `Undo/Follow` to be sent. The community removes the user from its follower list after receiving it.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/following/undo_follow.json}}
|
||||
```
|
||||
|
||||
|
||||
#### Report Post or Comment
|
||||
|
||||
Reports a post or comment for rule violation, so that mods/admins review it.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/community/report_page.json}}
|
||||
```
|
||||
|
||||
### Community to User
|
||||
|
||||
#### Accept Follow
|
||||
|
||||
Automatically sent by the community in response to a `Follow`. At the same time, the community adds this user to its followers list.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/following/accept.json}}
|
||||
```
|
||||
|
||||
#### Announce
|
||||
|
||||
When the community receives a post or comment activity, it wraps that into an `Announce` and sends it to all followers.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/community/announce_create_page.json}}
|
||||
```
|
||||
|
||||
### Announcable
|
||||
|
||||
All of these activities are sent from a user to a community. The community then wraps it in an Announce activity, and sends it to its followers.
|
||||
|
||||
#### Create or Update Post
|
||||
|
||||
When a user creates a new post, it is sent to the respective community. Editing a previously created post sends an almost identical activity, except the `type` being `Update`. We don't support mentions in posts yet.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/create_or_update/create_page.json}}
|
||||
```
|
||||
|
||||
#### Create or Update Comment
|
||||
|
||||
A reply to a post, or to another comment. Can contain mentions of other users. Editing a previously created post sends an almost identical activity, except the `type` being `Update`.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/create_or_update/create_note.json}}
|
||||
```
|
||||
|
||||
#### Like Post or Comment
|
||||
|
||||
An upvote for a post or comment.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/voting/like_note.json}}
|
||||
```
|
||||
|
||||
#### Dislike Post or Comment
|
||||
|
||||
A downvote for a post or comment.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/voting/dislike_page.json}}
|
||||
```
|
||||
|
||||
#### Undo Like or Dislike Post or Comment
|
||||
|
||||
Remove a vote that was previously done by the same user.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/voting/undo_like_note.json}}
|
||||
```
|
||||
|
||||
#### Delete Post or Comment
|
||||
|
||||
Deletes a previously created post or comment. This can only be done by the original creator of that post/comment.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/deletion/delete_page.json}}
|
||||
```
|
||||
|
||||
#### Remove Post or Comment
|
||||
|
||||
Removes a post or comment. This can only be done by a community mod, or by an admin on the instance where the community is hosted. The difference to delete is that remove activities have a summary field, which contains the reason for removal, as provided by the mod/admin.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/deletion/remove_note.json}}
|
||||
```
|
||||
|
||||
#### Undo Delete or Remove
|
||||
|
||||
Reverts the action done by the activity in the object field. In this example, the removed Note is restored.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/deletion/undo_remove_note.json}}
|
||||
```
|
||||
|
||||
#### Add Mod
|
||||
|
||||
Add a new mod to the community. Has to be sent by an existing community mod, or an admin of the community's instance.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/community/add_mod.json}}
|
||||
```
|
||||
|
||||
#### Remove Mod
|
||||
|
||||
Remove an existing mod from the community. Has to be sent by an existing community mod, or an admin of the community's instance.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/community/remove_mod.json}}
|
||||
```
|
||||
|
||||
#### Block User
|
||||
|
||||
Blocks a user from a community, so he can't participate in it.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/community/block_user.json}}
|
||||
```
|
||||
|
||||
#### Undo Block User
|
||||
|
||||
Reverts a previous user block.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/community/block_user.json}}
|
||||
```
|
||||
|
||||
### User to User
|
||||
|
||||
#### Create or Update Private message
|
||||
|
||||
Creates a new private message between two users.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/private_message/create.json}}
|
||||
```
|
||||
|
||||
#### Delete Private Message
|
||||
|
||||
Deletes a previous private message.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/private_message/delete.json}}
|
||||
```
|
||||
|
||||
#### Undo Delete Private Message
|
||||
|
||||
Restores a previously deleted private message. The `object` is regenerated from scratch, as such the activity ID and other fields are different.
|
||||
|
||||
```json
|
||||
{{#include ../../../include/crates/apub/assets/lemmy/activities/private_message/undo_delete.json}}
|
||||
```
|
127
src/id/federation/overview.md
Normal file
127
src/id/federation/overview.md
Normal file
|
@ -0,0 +1,127 @@
|
|||
# Federation Overview
|
||||
|
||||
|
||||
This document is for anyone who wants to know how Lemmy federation works, without being overly technical. It is meant provide a high-level overview of ActivityPub federation in Lemmy. If you are implementing ActivityPub yourself and want to be compatible with Lemmy, read our [ActivityPub API outline](contributing_apub_api_outline.md).
|
||||
|
||||
## Documentation conventions
|
||||
|
||||
To keep things simple, sometimes you will see things formatted like `Create/Note` or `Delete/Event` or `Undo/Follow`. The thing before the slash is the Activity, and the thing after the slash is the Object inside the Activity, in an `object` property. So these are to be read as follows:
|
||||
|
||||
* `Create/Note`: a `Create` activity containing a `Note` in the `object` field
|
||||
* `Delete/Event`: a `Delete` activity containing an `Event` in the `object` field
|
||||
* `Undo/Follow`: an `Undo` activity containing a `Follow` in the `object` field
|
||||
|
||||
In Lemmy we use some specific terms to refer to ActivityPub items. They are essentially our specific implementations of well-known ActivityPub concepts:
|
||||
|
||||
- Community: `Group`
|
||||
- User: `Person`
|
||||
- Post: `Page`
|
||||
- Comment: `Note`
|
||||
|
||||
This document has three main sections:
|
||||
|
||||
* __Federation philosophy__ lays out the general model of how this is intended to federate
|
||||
* __User Activities__ describes which actions that a User can take to interact
|
||||
* __Community Activities__ describes what the Community does in response to certain User actions
|
||||
|
||||
## Federation philosophy
|
||||
|
||||
The primary Actor in Lemmy is the Community. Each community resides on a single instance, and consists of a list of Posts and a list of followers. The primary interaction is that of a User sending a Post or Comment related activity to the Community inbox, which then announces it to all its followers.
|
||||
|
||||
Each Community has a specific creator User, who is responsible for setting rules, appointing moderators, and removing content that violates the rules.
|
||||
|
||||
Besides moderation on the community level, each instance has a set of administrator Users, who have the power to do site-wide removals and bans.
|
||||
|
||||
Users follow Communities that they are interested in, in order to receive Posts and Comments. They also vote on Posts and Comments, as well as creating new ones. Comments are organised in a tree structure and commonly sorted by number of votes. Direct messages between Users are also supported.
|
||||
|
||||
Users can not follow each other, and neither can Communities follow anything.
|
||||
|
||||
Our federation implementation is already feature complete, but so far we haven't focused at all on complying with the ActivityPub spec. As such, Lemmy is likely not compatible with implementations which expect to send and receive valid activities. This is something we plan to fix in the near future. Check out [#698](https://github.com/LemmyNet/lemmy/issues/698) for an overview of our deviations.
|
||||
|
||||
## User Activities
|
||||
|
||||
### Follow a Community
|
||||
|
||||
Each Community page has a "Follow" button. Clicking this triggers a `Follow` activity to be sent from the user to the Community inbox. The Community will automatically respond with an `Accept/Follow` activity to the user inbox. It will also add the user to its list of followers, and deliver any activities about Posts/Comments in the Community to the user.
|
||||
|
||||
### Unfollow a Community
|
||||
|
||||
After following a Community, the "Follow" button is replaced by "Unfollow". Clicking this sends an `Undo/Follow` activity to the Community inbox. The Community removes the User from its followers list and doesn't send any activities to it anymore.
|
||||
|
||||
### Create a Post
|
||||
|
||||
When a user creates a new Post in a given Community, it is sent as `Create/Page` to the Community
|
||||
inbox.
|
||||
|
||||
### Create a Comment
|
||||
|
||||
When a new Comment is created for a Post, both the Post ID and the parent Comment ID (if it exists)
|
||||
are written to the `in_reply_to` field. This allows assigning it to the correct Post, and building
|
||||
the Comment tree. It is then sent to the Community inbox as `Create/Note`
|
||||
|
||||
The origin instance also scans the Comment for any User mentions, and sends the `Create/Note` to
|
||||
those Users as well.
|
||||
|
||||
### Edit a Post
|
||||
|
||||
Changes the content of an existing Post. Can only be done by the creating User.
|
||||
|
||||
### Edit a Comment
|
||||
|
||||
Changes the content of an existing Comment. Can only be done by the creating User.
|
||||
|
||||
### Likes and Dislikes
|
||||
|
||||
Users can like or dislike any Post or Comment. These are sent as `Like/Page`, `Dislike/Note` etc to the Community inbox.
|
||||
|
||||
### Deletions
|
||||
|
||||
The creator of a Post, Comment or Community can delete it. It is then sent to the Community followers. The item is then hidden from all users.
|
||||
|
||||
### Removals
|
||||
|
||||
Mods can remove Posts and Comments from their Communities. Admins can remove any Posts or Comments on the entire site. Communities can also be removed by admins. The item is then hidden from all users.
|
||||
|
||||
Removals are sent to all followers of the Community, so that they also take effect there. The exception is if an admin removes an item from a Community which is hosted on a different instance. In this case, the removal only takes effect locally.
|
||||
|
||||
### Revert a previous Action
|
||||
|
||||
We don't delete anything from our database, just hide it from users. Deleted or removed Communities/Posts/Comments have a "restore" button. This button generates an `Undo` activity which sets the original delete/remove activity as object, such as `Undo/Remove/Post` or `Undo/Delete/Community`.
|
||||
|
||||
Clicking on the upvote button of an already upvoted post/comment (or the downvote button of an already downvoted post/comment) also generates an `Undo`. In this case and `Undo/Like/Post` or `Undo/Dislike/Comment`.
|
||||
|
||||
### Create private message
|
||||
|
||||
User profiles have a "Send Message" button, which opens a dialog permitting to send a private message to this user. It is sent as a `Create/Note` to the user inbox. Private messages can only be directed at a single User.
|
||||
|
||||
### Edit private message
|
||||
|
||||
`Update/Note` changes the text of a previously sent message
|
||||
|
||||
### Delete private message
|
||||
|
||||
`Delete/Note` deletes a private message.
|
||||
|
||||
### Restore private message
|
||||
|
||||
`Undo/Delete/Note` reverts the deletion of a private message.
|
||||
|
||||
## Community Activities
|
||||
|
||||
The Community is essentially a bot, which will only do anything in reaction to actions from Users. The User who first created the Community becomes the first moderator, and can add additional moderators. In general, whenever the Community receives a valid activity in its inbox, that activity is forwarded to all its followers.
|
||||
|
||||
### Accept follow
|
||||
|
||||
If the Community receives a `Follow` activity, it automatically responds with `Accept/Follow`. It also adds the User to its list of followers.
|
||||
|
||||
### Unfollow
|
||||
|
||||
Upon receiving an `Undo/Follow`, the Community removes the User from its followers list.
|
||||
|
||||
### Announce
|
||||
|
||||
If the Community receives any Post or Comment related activity (Create, Update, Like, Dislike, Remove, Delete, Undo), it will Announce this to its followers. For this, an Announce is created with the Community as actor, and the received activity as object. Following instances thus stay updated about any actions in Communities they follow.
|
||||
|
||||
### Delete Community
|
||||
|
||||
If the creator or an admin deletes the Community, it sends a `Delete/Group` to all its followers.
|
23
src/id/moderation/moderation.md
Normal file
23
src/id/moderation/moderation.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Aksi moderasi
|
||||
|
||||
Di Lemmy, **moderator** adalah seseorang yang mengelola dan punya hak terhadap sebuah komunitas.
|
||||
|
||||
**Pembuat komunitas** merupakan **moderator** pertama sebuah komunitas karena mereka membuatnya.
|
||||
|
||||
Seorang **administrator** memiliki hak penuh terhadap seluruh apa yang ada di peladen, dan demikian juga terhadap seluruh komunitas.
|
||||
|
||||
| Aksi | Hasil | Tingkat izin |
|
||||
| --- | --- | --- |
|
||||
| kunci | Cegah membuat komentar baru di bawah sebuah pos | Moderator |
|
||||
| tempel | Semat publikasi ke atas daftar komunitas | Moderator |
|
||||
| hapus | Hapus pos | Moderator |
|
||||
| larang | Larang pengguna dari komunitas | Moderator |
|
||||
| angkat menjadi mod | Berikan pengguna status moderator | Moderator |
|
||||
| angkat menjadi admin | Berikan pengguna status admin | Admin |
|
||||
| larang dari situs | Larang pengguna dari peladen | Admin |
|
||||
|
||||
Untuk melakukan aksi moderasi pada seorang pengguna, Anda memerlukan pos dari pengguna tersebut dan klik 3 titik di kanan bawah dari judul.
|
||||
|
||||
Untuk mengurungkan aksi yang sebelumnya dilakukan pada seorang pengguna, proses yang sama harus diikuti. Seperti contoh, jika sebuah pos dikunci, klik pada ikon kunci lagi untuk membuka kuncinya.
|
||||
|
||||
![more_button.png](more_button.png)
|
BIN
src/id/moderation/more_button.png
Normal file
BIN
src/id/moderation/more_button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
Loading…
Reference in a new issue