Commit 246d57d5 authored by rinpatch's avatar rinpatch

Add middleman, blog, announcements

parent 59a761dd
Pipeline #22227 passed with stage
in 1 minute and 51 seconds
source/images/** filter=lfs diff=lfs merge=lfs -text
- build
- deploy
stage: build
image: ruby
key: ${CI_JOB_NAME}
- vendor/ruby
- build
- bundle install -j $(nproc) --path vendor/ruby
- bundle exec middleman build
stage: deploy
image: alpine:3.9
......@@ -13,4 +29,4 @@ deploy:
- echo "${SSH_HOST_KEY}" > ~/.ssh/known_hosts
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- rsync -hrvz --delete -e "ssh -p ${SSH_PORT}" ./ "${SSH_USER_HOST_LOCATION}"
- rsync -hrvz --delete -e "ssh -p ${SSH_PORT}" ./build/* "${SSH_USER_HOST_LOCATION}"
source ''
gem 'middleman', '~> 4.2'
gem 'middleman-autoprefixer', '~> 2.7'
gem 'tzinfo-data', platforms: [:mswin, :mingw, :jruby, :x64_mingw]
gem 'wdm', '~> 0.1', platforms: [:mswin, :mingw, :x64_mingw]
gem "http", "~> 4.2"
gem "htmlbeautifier", "~> 1.3"
gem "middleman-minify-html", "~> 3.4"
gem "middleman-blog", "~> 4.0"
gem "nokogiri", "~> 1.10"
gem "redcarpet", "~> 3.5"
gem "font-awesome-middleman", "~> 4.2"
gem "builder"
gem "mini_racer"
activesupport (
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
autoprefixer-rails (9.7.1)
backports (3.15.0)
builder (3.2.4)
coffee-script (2.4.1)
coffee-script-source (1.12.2)
concurrent-ruby (1.1.5)
contracts (0.13.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.5)
erubis (2.7.0)
execjs (2.7.0)
fast_blank (1.0.0)
fastimage (2.1.7)
ffi (1.11.1)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
font-awesome-middleman (4.2.1)
middleman-core (>= 3.0.0)
haml (5.1.2)
temple (>= 0.8.0)
hamster (3.0.0)
concurrent-ruby (~> 1.0)
hashie (3.6.0)
htmlbeautifier (1.3.1)
htmlcompressor (0.2.0)
http (4.2.0)
addressable (~> 2.3)
http-cookie (~> 1.0)
http-form_data (~> 2.0)
http-parser (~> 1.2.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
http-form_data (2.1.1)
http-parser (1.2.1)
ffi-compiler (>= 1.0, < 2.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
kramdown (1.17.0)
libv8 (7.3.492.27.1)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
memoist (0.16.1)
middleman (4.3.5)
coffee-script (~> 2.2)
haml (>= 4.0.5)
kramdown (~> 1.2)
middleman-cli (= 4.3.5)
middleman-core (= 4.3.5)
middleman-autoprefixer (2.10.1)
autoprefixer-rails (~> 9.1)
middleman-core (>= 3.3.3)
middleman-blog (4.0.3)
addressable (~> 2.3)
middleman-core (>= 4.0.0)
tzinfo (>= 0.3.0)
middleman-cli (4.3.5)
thor (>= 0.17.0, < 2.0)
middleman-core (4.3.5)
activesupport (>= 4.2, < 5.1)
addressable (~> 2.3)
backports (~> 3.6)
contracts (~> 0.13.0)
execjs (~> 2.0)
fastimage (~> 2.0)
hamster (~> 3.0)
hashie (~> 3.4)
i18n (~> 0.9.0)
listen (~> 3.0.0)
memoist (~> 0.14)
padrino-helpers (~> 0.13.0)
rack (>= 1.4.5, < 3)
sassc (~> 2.0)
tilt (~> 2.0.9)
uglifier (~> 3.0)
middleman-minify-html (3.4.1)
htmlcompressor (~> 0.2.0)
middleman-core (>= 3.2)
mini_portile2 (2.4.0)
mini_racer (0.2.9)
libv8 (>= 6.9.411)
minitest (5.13.0)
nokogiri (1.10.5)
mini_portile2 (~> 2.4.0)
padrino-helpers (
i18n (~> 0.6, >= 0.6.7)
padrino-support (=
tilt (>= 1.4.1, < 3)
padrino-support (
activesupport (>= 3.1)
parallel (1.18.0)
public_suffix (4.0.1)
rack (2.0.7)
rake (13.0.0)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
redcarpet (3.5.0)
sassc (2.2.1)
ffi (~> 1.9)
servolux (0.13.0)
temple (0.8.2)
thor (0.20.3)
thread_safe (0.3.6)
tilt (2.0.10)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uglifier (3.2.0)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext (
font-awesome-middleman (~> 4.2)
htmlbeautifier (~> 1.3)
http (~> 4.2)
middleman (~> 4.2)
middleman-autoprefixer (~> 2.7)
middleman-blog (~> 4.0)
middleman-minify-html (~> 3.4)
nokogiri (~> 1.10)
redcarpet (~> 3.5)
wdm (~> 0.1)
desc "Format the sources"
task :format do
system('htmlbeautifier source/*.html.erb')
system('htmlbeautifier source/layouts/layout.erb')
system('htmlbeautifier source/layouts/article.erb')
system('htmlbeautifier source/_base_head.erb')
system('htmlbeautifier source/_navbar.erb')
system('htmlbeautifier source/_navbar_link.erb')
system('htmlbeautifier source/_footer.erb')
system('htmlbeautifier source/_article_list.erb')
# Activate and configure extensions
# Kramdown doesn't support embedded html
set :markdown_engine, :redcarpet
set :markdown, :fenced_code_blocks => true
activate :autoprefixer do |prefix|
prefix.browsers = "last 2 versions"
activate :directory_indexes
# Layouts
# Per-page layout changes
page '/*.xml', layout: false
page '/*.json', layout: false
page '/*.txt', layout: false
page '/index.html', layout: false
# With alternative layout
# page '/path/to/file.html', layout: 'other_layout'
# Proxy pages
# proxy(
# '/this-page-has-no-template.html',
# '/template-file.html',
# locals: {
# which_fake_page: 'Rendering a fake page with a local variable'
# },
# )
# Helpers
# Methods defined in the helpers block are available in templates
# helpers do
# def some_helper
# 'Helping'
# end
# end
helpers do
def homepage?
current_page.url == "/"
def gitlab_page_path
def article_date(date)
date.strftime('%B %e, %Y')
def prod_url()
# Build-specific configuration
activate :blog do |blog|
blog.prefix = "blog" = "blog"
blog.summary_separator = /<!--more-->/
blog.paginate = true
blog.layout = "article"
blog.tag_template = "blog_tag.html"
activate :blog do |blog|
blog.prefix = "announcements" = "announcements"
blog.summary_separator = /<!--more-->/
blog.paginate = true
blog.layout = "article"
blog.tag_template = "announcements_tag.html"
# Generate ATOM feeds
feed_locals = {:blog => {:title => "Pleroma Blog"}, :announcements => {:title => "Pleroma Admin Announcements"}}
ready do
app.extensions[:blog].each do |_key, blog|
proxy(blog.options.prefix.to_s + "/feed.xml","/feed.xml",:locals => { :blog_data =>, :html => blog.options.prefix.to_s }.merge(feed_locals[])) do |tag, _articles|
# tags don't have trailing .html when directory indexes are activated
tag_html_path =".html")
tag_feed_path = tag_html_path + "/feed.xml"
proxy(tag_feed_path,"/feed.xml",:locals => { :blog_data =>, :tagname => tag, :html => tag_html_path}.merge(feed_locals[]))
ignore "/feed.xml"
configure :build do
activate :minify_css
activate :minify_javascript
activate :minify_html
<article class="article-list">
<% if defined?(tagname) %>
<h1 class="article-list-title"> <% if blog.options[:name] == "announcements" %>Announcements<% else %>Posts<% end %> tagged <span class="highlight"> <%= tagname %> </span> </h1>
<% end %>
<% page_articles.each_with_index do |article, i| %>
<div class="article-short">
<div class="article-meta article-short-date" > <a href="<%= article.url %>"> <time> <%= article_date( %> </time> </a> </div>
<div class="article-short-summary">
<div class="article-meta article-short-tags" >
<ul class="enumeration">
<% article.tags.each do |tag| %>
<li><a href="<%= tag_path(tag) %>"><%= tag %></a></li>
<% end %>
<a class="article-short-title" href="<%= article.url %>">
<h2> <%= article.title %> </h2>
<div class="article-short-summary-content">
<p> <%= || article.summary %> </p>
<% end %>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=5.0">
<title><%= || "Pleroma" %></title>
<%= stylesheet_link_tag "normalize" %>
<%= stylesheet_link_tag "default" %>
<link rel="apple-touch-icon" sizes="180x180" href="/images/pleroma_logo_vector_bg_180.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/pleroma_logo_vector_bg_32.png">
<div class="footer">
<div class="footer-legal">
<a href="<%= gitlab_page_path %>"> View Source </a>
<a href=""> CC-BY 4.0 </a>
<div class="footer-social-icons">
<% if defined?(tagname) %>
<% link1 = current_page.url + "/feed.xml" %>
<% text1 = (blog.options[:name] == "announcements" ? "Announcements" : "Posts") + " tagged \"" + tagname + "\"" %>
<% else %>
<% if blog.options[:name] == "announcements" %>
<% link1 = blog.options.prefix + "/tags/stable/feed.xml" %>
<% text1 = "Stable announcements" %>
<% else %>
<% link1 = blog.options.prefix + "/tags/release/feed.xml" %>
<% text1 = "Release posts" %>
<% end %>
<% end %>
<% link2 = blog.options.prefix + "/feed.xml" %>
<% text2 = "All " + (blog.options[:name] == "announcements" ? "announcements" : "posts") %>
<a class="footer-rss-link" rel="alternate" type="application/rss+xml" href="<%= link1 %>" > <i class="icon-rss"> </i>
<p><%= text1 %></p>
<a class="footer-rss-link" rel="alternate" type="application/rss+xml" href="<%= link2 %>" > <i class="icon-rss"> </i>
<p><%= text2 %></p>
<div class="navbar-header-container">
<div class="navbar-header">
<% unless homepage? %>
<div class="navbar-brand" >
<a href="/" >
<div class="navbar-brand-logo"> </div>
<i class="icon-home"> </i>
<% end %>
<%= partial(:navbar_link, :locals => { :href => "", :text => "Documentation", :icon => "book" }) %>
<%= partial(:navbar_link, :locals => { :href => "/blog/", :text => "Blog", :icon => "newspaper" }) %>
<%= partial(:navbar_link, :locals => { :href => "/announcements/", :text => "Admin announcements", :icon => "megaphone" }) %>
<a href="<%= href %>">
<% if current_page.url.start_with?(href) %>
<div class="navbar-link selected">
<% else %>
<div class="navbar-link">
<% end %>
<i class="icon-<%= icon %>"> </i> <%= text %>
blog: announcements
<%= partial "article_list" %>
title: Rate limiter and Remote IP plug soon to be enabled by default again
date: 2020-01-25 10:28 UTC
tags: ["develop", "stable"]
authors: ["rinpatch"]
[Rate limiter]( was disabled by default in [!1601]( since the majority of Pleroma instances were behind reverse proxies and it didn't take `X-Forwarded-For` headers into account, rate limiting the reverse proxy IP instead.
Since then a [Remote IP plug]( was added to get the real IP from headers, but wasn't enabled by default because the default nginx config didn't forward the header and allowed spoofing it.
If you use any other reverse proxy we officially support other than nginx, or set up the instance after September 2019, no action is required on your part. Otherwise add the following to your `location /` block:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
If you want to explicitly disable rate limiting and the Remote IP plug (i.e if you run a tor/i2p instance) you can do that by adding the following to your config:
config :pleroma, Pleroma.Plugs.RemoteIp, enabled: false
config :pleroma, :rate_limit, nil
blog: announcements
<%= partial "article_list" %>
blog: blog
<%= partial "article_list" %>
title: "Gopher Support in Pleroma"
date: 2018-04-01T04:01:00+02:00
tags: ["Gopher", "April Fools", "rokalife"]
authors: ["lain"]
images: [
] # overrides the site-wide open graph image
<small> *Note: this has originally been posted at <>* </small>
As you may already know, [Pleroma](/) is high-performance and low-resource fediverse server mean to run even on small devices like a Raspberry Pi.
Still, there is one part of Pleroma that is wasteful to the extreme...
<img src='/images/no-js.png' class=fit />
It's true! Pleroma's mother allowed it to have TWO frontends, but both are resource-hogging Javascript monstrosities. If you don't have a 'modern' browser that turns your PC into a heater, you won't be able to see any posts!
So where did we go wrong? I think the problem goes way back. We made a deal with the Devil when we accepted free-form HTML into our systems. The best solution is to not make this mistake anymore, and go back to the future to a better alternative.
And that's why, today, I'm announcing [Gopher]( support for Pleroma!
You can try it out right now! Install a gopher compatible browser like Lynx and run `lynx gopher://`. This is what you'll see.
<img src="/images/lynx-1.png" class=fit />
Simplicity is perfection! You can easily read any of the public timelines through this.
<img src="/images/lynx-2.png" class=fit />
And of course you can also see conversations in a thread view. This should be enough for 90% of our social network needs, while being a hundred times more efficient than HTML, with JS or without.
<img src="/images/lynx-3.png" class=fit />
I hope that with this recent change, it is clear once again that Pleroma is always innovating for better resource usage and efficient computing. Have fun and see you on the fediverse!
title: "Pleroma's First Release! 0.9.9"
date: 2019-02-22T13:58:34+01:00
tags: ["Release"]
authors: ["lain"]
images: [
] # overrides the site-wide open graph image
<small> *Note: this has originally been posted at <>* </small>
The [first commit]( in Pleroma happened 2016, on October 26th. Now it's a few years and months later, and we are doing our first stable release!
Are you still running `develop`? That's so 2018.
<img class=fit src="/images/0.9.9.screenshot.png" />
[Pleroma]( has been growing a lot last year. According to [fediverse statistics](, we now have over 400 instances online on the network. We are seeing more people use it everyday, because it is easy to setup and runs on small devices like a Raspberry Pi.
For a rather long time, only I was running a Pleroma instance. For another long time, maybe 10 or 20 other instances were online. With a community of that size, it was easy to tell everyone to just use the development branch and notify them when something breaky happened. But by now we have around 80 contributors and over 400 admins and not every piece of code is written or reviewed by me. This led to a few rather rough upgrades, which could have been avoided by having a stable branch.
<img class=fit src="/images/0.9.9.screenshot-masto.png" />
So today, I am releasing the first stable Pleroma release, Pleroma 0.9.9 (a very strong release, maybe the strongest!). So why should you use it? Here are the nice things about it:
- Only tested features in it
- Will receive bugfixes
- Will have changelogs between releases
- I run it on my server so I'll know what breaks :)
By now, Pleroma has become a useful tool for thousands of users and this stable release is a great milestone to promote this.
If you want, you can still run on the `develop` branch, but expect this one to be in flux a lot.
Thanks to everyone who works on Pleroma! Thanks to everyone who reports bugs! And a big thank you if you are using Pleroma! Let's continue to make Pleroma better together in 2019!
You can find the release at [our Gitlab]( or download the tar.gz right [here](/misc/pleroma-v0.9.9.tar.gz).
title: "Fighting the Bloat! SSH Support in Pleroma"
date: 2019-04-01T04:01:00+02:00
tags: ["BBS", "SSH", "April Fools", "rokalife"]
authors: ["lain"]
images: [
] # overrides the site-wide open graph image
<small> *Note: this has originally been posted at <>* </small>
Pretty much one year ago, we started fighting the typical Web 4.0 Javascript bloat by adding [Gopher support](/blog/2018/04/01/gopher/). After a wildly successful [0.999 release](/blog/2019/02/22/pleroma-0-9-9/), we heard your calls for more debloating. The biggest complaint with the gopher support was the inability to post. So today, we're taking it a step further: Making Pleroma a BBS.
<img src='/images/pleroma-ssh-help.png' class=fit />
If you are a time traveller from the 19th century, you might remember that there was a time before the internet. It was the [age of the BBS](, a technology now long forgotten.
A BBS (Bulletin Board System) is a program someone used to run on their computer that would make it possible for other people to call in - literally - with a modem and read and send messages, chat and do general social things. They were so popular that some people got huge phone bills because they dialed in so much. Why did they do it? Same reason we use social networks today: They didn't have any friends!
One big advantage of the BBS format in comparison to HTML/JS is that it is text-only, no markup at all, no images and no virtual machine needed to subsidize the RAM industry. Now, we know that you probably don't have an actual modem at home, and most servers won't be attached to one. So here's the next best thing to a number you can dial in to: An ssh server!
<video controls class=fit>
<source src='/images/bbs-recode.mp4' type='video/mp4' />
As you can see, you can log in with your existing account an password and enjoy the super high speed of modern pipes with text-only interfaces. You can check your home timeline, post something, and even reply! Is it useful? Not really, but I'm sure rinpatch will fix that!
So how do you actually run this on your server? Well, it is still in development, but you can try it out right now by checking out the [BBS]( branch over at our Gitlab server. Just follow the instructions in `docs/` and you should be running your own BBS in no time! Hack the planet!
title: "Pleroma 1.0.0"
date: 2019-06-28T14:37:36+02:00
authors: ["lain"]
tags: ["Release"]
images: [
<small> *Note: this has originally been posted at <>* </small>
After long months of doing only bugfix and security releases, we are finally releasing the long-awaited 1.0 release. No more nines!
<img class=fit src="/images/pleroma_1.png" />
[Pleroma 1.0.0 is here!](
By now, you all know how great [Pleroma]( is. It is your favorite free software federated social network, written in Elixir. If you don't really know it yet, check out [this post]({{< relref "">}}).
We think we have achieved a state of the project that we can call 1.0. Let me talk a bit about all the new stuff we have in store for you.
## Polls
<img class=fit src="/images/pleroma_polls.png" />
You know them from your second-favorite social network, and now you can also make funny polls in Pleroma. The rules for them are a bit more relaxed than elsewhere: You can make a lot of options and attach pictures if you want. Want to know if Rei or Asuka is best girl? You can find out!
## Docs!
[DOCS!]( Finally you don't have to find us on IRC anymore to figure out how to install new emojis.
## OTP Releases!
OTP releases should be very interesting for you if you are hosting your own Pleroma server. They bundle the compiled Pleroma code with the necessary runtime files of Erlang and Elixir, so you won't need to install those seperately. It is kind of like 'binary releases' for Pleroma. Check out the [documentation]( and how to [switch]( from the current source based installation method. It will also allow you to change configuration settings without recompilation.
A word of warning: This method of release is still slightly experimental, so if you encounter anything weird, please file an issue on the [tracker]( and switch back to the source based installation if needed.
## Lots of other stuff!
Check out the [changelog]( and the [docs]( to find more cool new stuff, like emoji packs, mix tasks that will help you keep your database small, mongooseim integration to share accounts with an XMPP server... and so on :)
## Thanks!
First I want to thank YOU for reading my blog post.
Then I want to thank all the people who work on Pleroma. There are too many by now too mention by name, and I'm thankful for all of them. You made all this possible. Without code to base it on, there wouldn't be a fediverse community.
I also want to thank everybody who contributes to Pleroma in a way that's not code. If you write issues in the bug tracker, run an instance for yourself or other, or donate your time and money in another way, it is very appreciated.
Last, I want to thank the fediverse community. Working on Pleroma is fun for the technology, but you make it fun to actually use this stuff :)
Look forward to a great year for Pleroma and the Fediverse. Let's make 2.0 happen sooner :)
Now I'm off to Pyongyang to escape all this social network stuff, see ya!
blog: blog
<%= partial "article_list" %>
xml.feed "xmlns" => "" do
site_url = prod_url()
xml.title (defined?(tagname) ? tagname + " — " + title : title) URI.join(site_url, html) "href" => URI.join(site_url, html) "href" => URI.join(site_url, current_page.path), "rel" => "self"
xml.updated( unless blog_data.articles.empty?
blog_data.articles.each do |article|
xml.entry do
xml.title article.title "rel" => "alternate", "href" => URI.join(site_url, article.url) URI.join(site_url, article.url)
xml.updated File.mtime(article.source_file).iso8601
if[:authors] { do |author| author
xml.content article.body, "type" => "html"
This diff is collapsed.