2018-05-18 18:41:41 +00:00
# microblog.pub
< p align = "center" >
< img
src="https://sos-ch-dk-2.exo.io/microblogpub/microblobpub.png"
width="200" height="200" border="0" alt="microblog.pub">
< / p >
< p align = "center" >
2019-04-11 20:09:31 +00:00
< a href = "https://d.a4.io/tsileo/microblog.pub" > < img src = "https://d.a4.io/api/badges/tsileo/microblog.pub/status.svg" alt = "Build Status" > < / a >
2018-06-27 21:27:48 +00:00
< a href = "https://matrix.to/#/#microblog.pub:matrix.org" > < img src = "https://img.shields.io/badge/matrix-%23microblog.pub-blue.svg" alt = "#microblog.pub on Matrix" > < / a >
2018-05-20 10:28:11 +00:00
< a href = "https://github.com/tsileo/microblog.pub/blob/master/LICENSE" > < img src = "https://img.shields.io/badge/license-AGPL_3.0-blue.svg?style=flat" alt = "License" > < / a >
2019-04-13 08:01:55 +00:00
< a href = "https://github.com/ambv/black" > < img alt = "Code style: black" src = "https://img.shields.io/badge/code%20style-black-000000.svg" > < / a >
2018-05-18 18:41:41 +00:00
< / p >
2019-04-11 20:09:31 +00:00
2018-05-18 18:41:41 +00:00
< p align = "center" > A self-hosted, single-user, < a href = "https://activitypub.rocks" > ActivityPub< / a > powered microblog.< / p >
2018-05-20 10:28:11 +00:00
**Still in early development.**
2019-04-15 19:32:58 +00:00
## /!\ Note to adventurer
2019-04-11 18:22:38 +00:00
2019-04-15 19:32:58 +00:00
If you are running an instance with Celery/RabbitMQ, you will need to [perform a migration ](https://github.com/tsileo/microblog.pub/tree/drop-celery#perform-the-drop-celery-migration ).
2019-04-11 18:22:38 +00:00
2019-04-15 19:32:58 +00:00
Getting closer to a stable release, it should be the "last" migration.
2019-04-11 18:22:38 +00:00
2018-05-18 18:41:41 +00:00
## Features
- Implements a basic [ActivityPub ](https://activitypub.rocks/ ) server (with federation)
- Compatible with [Mastodon ](https://github.com/tootsuite/mastodon ) and others (Pleroma, Hubzilla...)
- Also implements a remote follow compatible with Mastodon instances
2018-05-20 10:28:11 +00:00
- Exposes your outbox as a basic microblog
2019-04-22 07:49:10 +00:00
- Support all content types from the Fediverse (`Note`, `Article` , `Page` , `Video` , `Image` , `Question` ...)
2018-06-21 22:20:58 +00:00
- Comes with an admin UI with notifications and the stream of people you follow
2018-05-20 10:28:11 +00:00
- Allows you to attach files to your notes
- Privacy-aware image upload endpoint that strip EXIF meta data before storing the file
2018-06-21 22:20:58 +00:00
- No JavaScript, **that's it** . Even the admin UI is pure HTML/CSS
2018-05-18 18:41:41 +00:00
- Easy to customize (the theme is written Sass)
2018-05-25 21:57:29 +00:00
- mobile-friendly theme
- with dark and light version
2018-05-18 18:41:41 +00:00
- Microformats aware (exports `h-feed` , `h-entry` , `h-cards` , ...)
2018-06-21 22:20:58 +00:00
- Exports RSS/Atom/[JSON](https://jsonfeed.org/) feeds
- You stream/timeline is also available in an (authenticated) JSON feed
- Comes with a tiny HTTP API to help posting new content and and read your inbox/notifications
2018-05-26 08:43:05 +00:00
- Deployable with Docker (Docker compose for everything: dev, test and deployment)
2019-04-22 07:49:10 +00:00
- Implements [IndieAuth ](https://indieauth.spec.indieweb.org/ ) endpoints (authorization and token endpoint)
- U2F support
- You can use your ActivityPub identity to login to other websites/app
2018-06-21 22:20:58 +00:00
- Focused on testing
- Tested against the [official ActivityPub test suite ](https://test.activitypub.rocks/ ) ([report submitted](https://github.com/w3c/activitypub/issues/308))
2019-04-15 19:32:58 +00:00
- [CI runs "federation" tests against two instances ](https://d.a4.io/tsileo/microblog.pub )
2019-04-22 07:49:10 +00:00
- Project is running 2 up-to-date instances ([here](https://microblog.pub) and [there ](https://a4.io ))
- The core ActivityPub code/tests are in [Little Boxes ](https://github.com/tsileo/little-boxes ) (but needs some cleanup)
- Manually tested against [Mastodon ](https://github.com/tootsuite/mastodon ) and other platforms
2018-05-18 18:41:41 +00:00
2018-05-27 09:01:34 +00:00
## ActivityPub
2019-04-22 08:52:32 +00:00
_microblog.pub_ implements an [ActivityPub ](http://activitypub.rocks/ ) server, it implements both the client to server API and the federated server to server API.
2018-05-27 09:01:34 +00:00
Activities are verified using HTTP Signatures or by fetching the content on the remote server directly.
2019-04-22 08:52:32 +00:00
## User Guide
The easiest and recommended way to run _microblog.pub_ in production is to use the provided docker-compose config.
First install [Docker ](https://docs.docker.com/install/ ) and [Docker Compose ](https://docs.docker.com/compose/install/ ).
It's the only requirements, Python is not needed on the host system.
Note that all the generated data (config included) will be stored on the host (i.e. not in Docker) in `config/` and `data/` .
2018-05-18 18:41:41 +00:00
### Installation
```shell
2018-06-03 14:25:21 +00:00
$ git clone https://github.com/tsileo/microblog.pub
$ cd microblog.pub
2019-04-22 08:52:32 +00:00
$ make config
2018-05-18 18:41:41 +00:00
```
2019-04-22 08:52:32 +00:00
### Deployment
2018-06-03 14:39:46 +00:00
2019-04-22 08:52:32 +00:00
To spawn the docker-compose project (running this command will also update _microblog.pub_ to latest and restart the project it it's already running):
2018-06-03 14:39:46 +00:00
2019-04-22 08:52:32 +00:00
```shell
$ make run
2018-05-18 18:41:41 +00:00
```
2019-04-22 08:52:32 +00:00
### Backup
2018-05-18 18:41:41 +00:00
2019-04-22 08:52:32 +00:00
The easiest way to backup all of your data is to backup the `microblog.pub/` directory directly (that's what I do and I have been able to restore super easily).
It should be safe to copy the directory while the docker-compose is running.
2018-05-18 18:41:41 +00:00
## Development
2019-04-22 08:52:32 +00:00
The project requires Python3.7+.
2018-05-18 18:41:41 +00:00
2019-04-22 08:52:32 +00:00
The most convenient way to hack on _microblog.pub_ is to run the Python server on the host directly, and evetything else in Docker.
2018-05-18 18:41:41 +00:00
```shell
2019-04-22 08:52:32 +00:00
# One-time setup (in a new virtual env)
2018-05-18 18:41:41 +00:00
$ pip install -r requirements.txt
2019-04-15 19:32:58 +00:00
# Start MongoDB and poussetaches
2019-04-17 18:44:26 +00:00
$ make poussetaches
2019-04-22 08:52:32 +00:00
$ env POUSSETACHES_AUTH_KEY="< secret-key > " docker-compose -f docker-compose-dev.yml up -d
2018-05-18 18:41:41 +00:00
# Run the server locally
2019-04-22 08:52:32 +00:00
$ FLASK_DEBUG=1 MICROBLOGPUB_DEBUG=1 FLASK_APP=app.py POUSSETACHES_AUTH_KEY="< secret-key > " flask run -p 5005 --with-threads
2018-05-18 18:41:41 +00:00
```
2018-06-03 16:23:44 +00:00
## API
Your admin API key can be found at `config/admin_api_key.key` .
2018-06-01 18:29:44 +00:00
## ActivityPub API
### GET /
Returns the actor profile, with links to all the "standard" collections.
### GET /tags/:tag
Special collection that reference notes with the given tag.
### GET /stream
Special collection that returns the stream/inbox as displayed in the UI.
2018-05-29 19:36:05 +00:00
## User API
The user API is used by the admin UI (and requires a CSRF token when used with a regular user session), but it can also be accessed with an API key.
2018-05-29 19:47:28 +00:00
All the examples are using [HTTPie ](https://httpie.org/ ).
2018-05-29 19:36:05 +00:00
### POST /api/note/delete{?id}
2018-06-01 18:29:44 +00:00
Deletes the given note `id` (the note must from the instance outbox).
2018-05-29 19:36:05 +00:00
Answers a **201** (Created) status code.
You can pass the `id` via JSON, form data or query argument.
#### Example
```shell
2018-06-01 18:29:44 +00:00
$ http POST https://microblog.pub/api/note/delete Authorization:'Bearer < token > ' id=http://microblob.pub/outbox/< note_id > /activity
2018-05-29 19:36:05 +00:00
```
#### Response
```json
{
"activity": "https://microblog.pub/outbox/< delete_id > "
}
```
2018-07-22 20:28:40 +00:00
### POST /api/note/pin{?id}
Adds the given note `id` (the note must from the instance outbox) to the featured collection (and pins it on the homepage).
Answers a **201** (Created) status code.
You can pass the `id` via JSON, form data or query argument.
#### Example
```shell
$ http POST https://microblog.pub/api/note/pin Authorization:'Bearer < token > ' id=http://microblob.pub/outbox/< note_id > /activity
```
#### Response
```json
{
"pinned": true
}
```
### POST /api/note/unpin{?id}
Removes the given note `id` (the note must from the instance outbox) from the featured collection (and un-pins it).
Answers a **201** (Created) status code.
You can pass the `id` via JSON, form data or query argument.
#### Example
```shell
$ http POST https://microblog.pub/api/note/unpin Authorization:'Bearer < token > ' id=http://microblob.pub/outbox/< note_id > /activity
```
#### Response
```json
{
"pinned": false
}
```
2018-06-01 18:29:44 +00:00
### POST /api/like{?id}
Likes the given activity.
Answers a **201** (Created) status code.
You can pass the `id` via JSON, form data or query argument.
#### Example
```shell
$ http POST https://microblog.pub/api/like Authorization:'Bearer < token > ' id=http://activity-iri.tld
```
#### Response
```json
{
"activity": "https://microblog.pub/outbox/< like_id > "
}
```
### POST /api/boost{?id}
Boosts/Announces the given activity.
Answers a **201** (Created) status code.
You can pass the `id` via JSON, form data or query argument.
#### Example
```shell
$ http POST https://microblog.pub/api/boost Authorization:'Bearer < token > ' id=http://activity-iri.tld
```
#### Response
```json
{
"activity": "https://microblog.pub/outbox/< announce_id > "
}
```
### POST /api/block{?actor}
Blocks the given actor, all activities from this actor will be dropped after that.
Answers a **201** (Created) status code.
You can pass the `id` via JSON, form data or query argument.
#### Example
```shell
$ http POST https://microblog.pub/api/block Authorization:'Bearer < token > ' actor=http://actor-iri.tld/
```
#### Response
```json
{
"activity": "https://microblog.pub/outbox/< block_id > "
}
```
### POST /api/follow{?actor}
Follows the given actor.
Answers a **201** (Created) status code.
You can pass the `id` via JSON, form data or query argument.
#### Example
```shell
$ http POST https://microblog.pub/api/follow Authorization:'Bearer < token > ' actor=http://actor-iri.tld/
```
#### Response
```json
{
"activity": "https://microblog.pub/outbox/< follow_id > "
}
```
### POST /api/new_note{?content,reply}
Creates a new note. `reply` is the IRI of the "replied" note if any.
Answers a **201** (Created) status code.
You can pass the `content` and `reply` via JSON, form data or query argument.
#### Example
```shell
$ http POST https://microblog.pub/api/new_note Authorization:'Bearer < token > ' content=hello
```
#### Response
```json
{
"activity": "https://microblog.pub/outbox/< create_id > "
}
```
### GET /api/stream
#### Example
```shell
$ http GET https://microblog.pub/api/stream Authorization:'Bearer < token > '
```
#### Response
```json
```
2018-05-18 18:41:41 +00:00
## Contributions
PRs are welcome, please open an issue to start a discussion before your start any work.