Scoold is a Stack Overflow clone written in Java (self-hosted)
Clone or download
Latest commit 78af25d Jan 17, 2019

Scoold Q&A

Stack Overflow in a JAR

Join the chat at

Scoold is a Q&A platform written in Java. The project was created back in 2008, released in 2012 as social network for schools inspired by Stack Overflow. In 2017 it was refactored, repackaged and open-sourced.

Scoold can run anywhere - Heroku, DigitalOcean, AWS, Azure or any VPS hosting provider. It's lightweight (~4000 LOC), the backend is handled by a separate service called Para. Scoold does not require a database, and the controller logic is really simple because all the heavy lifting is delegated to Para. This makes the code easy to read and can be learned quickly by junior developers.

This project is fully funded and supported by Erudika - an independent, bootstrapped company.


  • Full featured Q&A platform
  • Database-agnostic, optimized for cloud deployment
  • Full-text search
  • Distributed object cache
  • Location-based search and "near me" filtering of posts
  • I18n with RTL language support
  • Reputation and voting system with badges
  • Spaces (Teams) - groups of isolated questions and users
  • Minimal frontend JS code based on jQuery
  • Modern, responsive layout powered by Materialize CSS
  • Suggestions for similar questions and hints for duplicate posts
  • Email notifications for post replies and comments
  • Spring Boot project (single JAR)
  • LDAP authentication support
  • Social login (Facebook, Google, GitHub, LinkedIn, Microsoft, Twitter) with Gravatar support
  • Syntax highlighting for code in posts, GFM markdown support with tables, task lists and strikethrough
  • Emoji support - cheat sheet
  • SEO friendly

Pro Features

  • Sticky / Favorite posts
  • SAML support
  • Anonymous posts
  • Unlimited spaces
  • Multiple admins
  • Multiple identity domains
  • Advanced syntax highlighting
  • Image uploads
  • Security notifications

Buy Scoold Pro 299 EUR

Live Demo

The demo is deployed on a free dyno and it might take a minute to wake up.

Live demo on Heroku

Quick Start (option 1 - managed Para backend, easier)

JDK 1.8 or higher is required to build and run the project.

  1. First, you need to create a developer app with Facebook, Google or any other identity provider that you wish to use. This isn't necessary if you're planning to login with LDAP, SAML or with a email and password. Save the obtained API keys in application.conf, as shown below.

Important: Authorized redirect URLs for Google and Facebook should look like this: https://{your_scoold_host}, https://{your_scoold_host}/signin. For all the other identity providers you must whitelist the Para host with the appropriate authentication endpoint. For example, for GitHub, the redirect URL could be:

  1. Create a new app on and copy your access keys to a file
  2. Click one of the quick deploy buttons:
btn btn btn

Quick Start (option 2 - self-hosted Para backend, harder)

Note: The Para backend server is deployed separately and is required for Scoold to run.

  1. Create a new app on and save the access keys in application.conf OR run Para locally on port 8080
  2. Create a separate application.conf for Scoold and configure it to connect to Para on port 8080
  3. Start Scoold on port 8000: java -jar -Dserver.port=8000 -Dconfig.file=./application.conf scoold.jar OR mvn spring-boot:run
  4. Open http://localhost:8000 in your browser

If you run Para locally, use the Para CLI tool to create a separate app for Scoold:

# run setup and enter the keys for the root app and endpoint 'http://localhost:8080'
$ para-cli setup
$ para-cli ping
$ para-cli new-app "scoold" --name "Scoold"

Important: Do not use the same application.conf file for both Para and Scoold! Keep the two applications in separate directories, each with its own configuration file. The settings shown below are all meant to be part of the Scoold config file.

Read the Para docs for more information.


Important: Create a separate app for Scoold, instead of using app:para.

The most important settings are para.endpoint - the URL of the Para server, as well as, para.access_key and para.secret_key. Connection to a Para server is required for Scoold to run.

This is an example of what your application.conf should look like:

para.app_name = "Scoold"
# the port for Scoold
para.port = 8000
# change this to "production" later
para.env = "development"
# the URL where Scoold is hosted, or http://localhost:8000
para.host_url = ""
# the URL of Para - could also be "http://localhost:8080"
para.endpoint = ""
# access key for your Para app
para.access_key = "app:scoold"
# secret key for your Para app
para.secret_key = "*****************"
# enable or disable email&password authentication
para.password_auth_enabled = false
# if false, commenting is allowed after 100+ reputation
para.new_users_can_comment = true
# needed for geolocation filtering of posts
para.gmaps_api_key = "********************************"
# the identifier of admin user - check Para user object
para.admins = ""
# GA code
para.google_analytics_id = "UA-123456-7"
# enables syntax highlighting in posts
para.code_highlighting_enabled = true
# Facebook - create your own Facebook app first!
para.fb_app_id = "123456789"
# Google - create your own Google app first!
para.google_client_id = ""
# If true, the default space will be accessible by everyone
para.is_default_space_public = true


Tagged Docker images for Scoold are located at erudikaltd/scoold on Docker Hub. First, have your Scoold application.conf configuration file ready in the current directory and run this command:

$ docker run -ti -p 8000:8000 --rm -v $(pwd)/application.conf:/scoold/application.conf \
  -e JAVA_OPTS="-Dconfig.file=/scoold/application.conf" erudikaltd/scoold

Environment variables

JAVA_OPTS - Java system properties, e.g. -Dpara.port=8000 BOOT_SLEEP - Startup delay, in seconds

Docker Compose

You can start the whole stack, Para + Scoold, with a single command using docker-compose. First, create a new directory and copy docker-compose.yml to it from this repository. Create these 4 files:

  1. para.env - containing environment variables for Para, like JAVA_OPTS
  2. scoold.env - containing environment variables for Scoold, like JAVA_OPTS
  3. para-application.conf - containing the Para configuration
  4. scoold-application.conf - containing the Scoold configuration

An example para.env file:


An scoold.env file:


Then you can start both Scoold and Para with Docker Compose like so:

$ docker-compose up

Deploying Scoold to Heroku

One-click deployment


Manual deployment

  1. First, clone this repository and create a new Heroku app
  2. Add Heroku as a Git remote target and push your changes with git push heroku master
  3. Go to the Heroku admin panel, under "Settings", "Reveal Config Vars" and set all the configuration variables shown above.
  4. Open the app in your browser at https://{appname}

Note: On Heroku, all configuration variables (config vars) must be set without dots ".", for example para.endpoint becomes para_endpoint.

It's also helpful to install the Heroku CLI tool.

Deploying Scoold to DigitalOcean

deploy to digitalocean button
  1. Click the button above and wait for the DO installer to finish.
  2. Send the configuration file to your droplet: scp application.conf root@
  3. Restart Scoold with ssh root@ "systemctl restart scoold.service"
  4. Go to (use the correct IP address)
  5. Configure SSL on DigitalOcean or install nginx + letsencrypt on your droplet

Deploying Scoold to AWS

deploy to aws button

Lightsail (recommended)

  1. Click the button above
  2. Choose "Linux", "OS only", "Ubuntu 18.04 LTS"
  3. Click "+ Add launch script" and copy/paste the contents of
  4. Download the default SSH key pair or upload your own
  5. Choose the 512MB instance or larger (1GB recommended)
  6. Wait for the instance and open the IP address in your browser

Elatic Beanstalk

  1. Clone this repo and change directory to it
  2. Generate a WAR package with mvn -Pwar package
  3. Create a new Beanstalk web app
  4. Upload the WAR package target/scoold-x.y.z.war to Beanstalk, modify any additional options and hit "Create"

Deploying Scoold to Azure

Deploy to Azure

  1. Click the button above
  2. Fill in the required parameters
  3. Launch the container

Deploying Scoold to Google App Engine

  1. Clone this repo and change directory to it
  2. Create a project in the Google Cloud Platform Console
  3. Install the Google Cloud SDK
  4. Delete Dockerfile and app.yml
  5. Edit app.gae.yaml to suit your needs
  6. Deploy it with gcloud preview app deploy app.gae.yaml

Deploying Scoold to a servlet container

The instructions for Tomcat in particular are:

  1. Generate a WAR package with mvn -Pwar package
  2. Rename the WAR package to ROOT.war if you want it deployed to the root context or leave it as is
  3. Put the WAR package in Tomcat/webapps/ & start Tomcat
  4. Put application.conf in Tomcat/webapps/scoold-folder/WEB-INF/classes/ & restart Tomcat

Scoold is compatible with Tomcat 9+.

Deploying Scoold under a specific context path

To deploy Scoold at a different path instead of the root path, set para.context_path = "/newpath. The default value for this setting is blank, meaning Scoold will be deployed at the root directory.

Content-Security-Policy header

This header is enabled by default for enhanced security. It can be disabled with para.csp_header_enabled = false. The default value is modified through para.csp_header = "new_value". The default CSP header is:

default-src 'self';
base-uri 'self';
connect-src 'self';
frame-src 'self';
script-src 'self' 'unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' https: data:; report-uri /reports/cspv

Note: If you get CSP violation errors, check you para.host_url configuration, or edit the value of para.csp_header.

Serving static files from a CDN

Scoold will serve static files (JS, CSS, fonts) from the same domain where it is deployed. You can configure the para.cdn_url to enable serving those files from a CDN. The value of the CDN URL will override para.host_url and must not end in "/".

SMTP configuration

Scoold uses the JavaMail API to send emails. If you want Scoold to send notification emails you should add the following SMTP settings to your config file:

# system email address
para.support_email = "" = ""
para.mail.port = 587
para.mail.username = ""
para.mail.password = "password"
para.mail.tls = true
para.mail.ssl = false

The email template is located in src/main/resources/emails/notify.html.

Social login

For authenticating with Facebook or Google, you only need your Google client id (e.g., or Facebook app id (only digits). For all the other providers, GitHub, LinkedIn, Twitter and Microsoft, you need to set both the app id and secret key. Note: if the credentials are blank, the sign in button is hidden for that provider.

# Facebook
para.fb_app_id = "123456789"
# Google
para.google_client_id = ""
# GitHub
para.gh_app_id = ""
para.gh_secret = ""
# LinkedIn
para.in_app_id = ""
para.in_secret = ""
# Twitter
para.tw_app_id = ""
para.tw_secret = ""
# Microsoft
para.ms_app_id = ""
para.ms_secret = ""

You also need to set your host URL when running Scoold in production:

para.host_url = "https://your.scoold.url"

This is required for authentication requests to be redirected back to the origin.

OAuth 2.0 login

You can authenticate users against your own OAuth 2.0/OpenID Connect server through the generic OAuth 2 filter in Para. Here are all the options which you can set in the Scoold configuration file:

# minimal setup
para.oa2_app_id = ""
para.oa2_secret = "" = "" = "" = ""

# extra options = "openid email profile" = "" = "sub" = "picture" = "email" = "name"

# Sets the string on the login button = "Continue with OpenID Connect"

LDAP configuration

LDAP authentication is initiated with a request like this POST /signin?provider=ldap&access_token=username:password. There are several configuration options which Para needs in order to connect to your LDAP server. These are the defaults: = "ldap://localhost:8389/" = "dc=springframework,dc=org" = "" = "" = "" = "(cn={0})" = "uid={0},ou=people" = "userPassword"
# set this only if you are connecting to Active Directory = ""

# Sets the string on the login button (PRO) = "Continue with LDAP"

For Active Directory LDAP, the search filter defaults to (&(objectClass=user)(userPrincipalName={0})). The syntax for this allows either {0} (replaced with username@domain) or {1} (replaced with username only).

SAML configuration

PRO First, you have to setup Para as a SAML service provider using the config below. Then you can exchange SAML metadata with your SAML identity provider (IDP). The SP metadata endpoint is /saml_metadata/{appid}. For example, if your Para endpoint is and your appid is scoold, then the metadata is available at

SAML authentication is initiated by sending users to the Para SAML authentication endpoint /saml_auth/{appid}. For example, if your Para endpoint is and your appid is scoold, then the user should be sent to Para (the service provider) will handle the request and redirect to the SAML IDP. Finally, upon successful authentication, the user is redirected back to which is also the assertion consumer service (ACS).

Note: The X509 certificate and private key must be encoded as Base64 in the configuration file. Additionally, the private key must be in the PKCS#8 format (---BEGIN PRIVATE KEY---). To convert from PKCS#1 to PKCS#8, use this:

openssl pkcs8 -topk8 -inform pem -nocrypt -in sp.rsa_key -outform pem -out sp.pem

There are lots of configuration options but Para needs only a few of those in order to successfully authenticate with your SAML IDP (listed in the first rows below).

# minimal setup
# IDP metadata URL, e.g. https://idphost/idp/shibboleth = ""

# SP endpoint, e.g. = ""

# SP public key as Base64(x509 certificate) = ""

# SP private key as Base64(PKCS#8 key) = ""

# attribute mappings (usually required)
# e.g. urn:oid:0.9.2342.19200300.100.1.1 = ""
# e.g. urn:oid:0.9.2342.19200300.100.1.3 = ""
# e.g. urn:oid: = ""

# extra options (optional)
# this is usually the same as the "EntityId" = "" = ""

# IDP metadata is usually automatically fetched = "" = "" = "" = false = false = false = false = false = false = true = "" = "" = "" = "" = ""

# Sets the string on the login button = "Continue with SAML"

Spaces (Teams)

Spaces are a way to organize users and questions into isolated groups. There's a default space, which is publicly accessible by default. Each user can belong to one or more spaces, but a question can only belong to a single space. Permission to access a space is given by an administrator. You can bulk edit users' spaces and also move a question to a different space.

By default there's a public "default" space where all questions go. When you create a new space and assign users to it they will still see all the other questions when they switch to the "default" space. To make the default space private set para.is_default_space_public = false.

PRO In Scoold PRO you can create as many space as you need. The open source version is limited to 10 spaces.

Domain-restricted user registrations

You can restrict signups only to users from a particular identity domain, say To do so, set the following configuration property:

para.approved_domains_for_signups = ""

Then a user with email will be allowed to login (the identity provider is irrelevant), but user will be denied access.

PRO In Scoold PRO this setting can also contain a comma-separated list of identity domains:

para.approved_domains_for_signups = ","


You can specify the user with administrative privileges in your application.conf file:

para.admins = ""

PRO In Scoold PRO you can have multiple admin users by specifying a comma-separated list of user identifiers. This works both for new and existing users.

para.admins = ",fb:1023405345366,gh:1234124"

If you remove users who are already admins from the list of admins para.admins, they will be demoted to regular users. Similarly, existing regular users will be promoted to admins if they appear in the list above.

Anonymous posts

PRO This feature is enabled with para.anonymous_posts_enabled = true. It allows everyone to ask questions and write replies, without having a Scoold account. Posting to the "Feedback" section will also be open without requiring users to sign in. This feature is disabled by default.

Disabling the "Feedback" section

PRO In Scoold PRO you can disable the "Feedback" functionality of the site by setting para.feedback_enabled = false. This will remove the link to /feedback and disable the feature entirely.

LaTeX/MathML support and advanced highlighting

PRO You can enable this feature by setting para.mathjax_enabled = true. Then you can use MathML expressions by surrounding them with $$ signs, e.g. $$ \frac {1}{2} $$ By default, MathJax is disabled.

The Prism syntax highlighter is included and it supports many different languages. You need to specify the language for each code block if you want the highlighting to be more accurate (see all supported languages). For example:

var dict = new Dictionary<string>();

Image uploads

PRO Image uploads are handled by Imgur. In the future, more upload services could be supported such as S3. To initiate a new image upload, open up the Markdown editor and drag'n'drop the image you want to upload. A link will automatically appear when the upload is finished. For this feature to work correctly you have to specify your Imgur API client id:

para.imgur_client_id = "x23e8t0askdj"

Self-hosting Para and Scoold through SSL

The recommended way for enabling HTTPS with your own SSL certificate in a self-hosted environment is to run a reverse-proxy server like NGINX in front of Scoold. As an alternative you can use Apache or Lighttpd.

  1. Start Para on port :8080
  2. Start Scoold on port :8000
  3. Start NGINX with the configuration below
Example configuration for NGINX
server_tokens off;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;

server {
  listen 80 default_server;
  listen [::]:80 default_server;

  # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
  return 301 https://$host$request_uri;

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
  ssl_certificate /path/to/signed_cert_plus_intermediates;
  ssl_certificate_key /path/to/private_key;
  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:50m;
  ssl_session_tickets off;

  # modern configuration. tweak to your needs.
  ssl_protocols TLSv1.2;
  ssl_prefer_server_ciphers on;

  # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
  add_header Strict-Transport-Security max-age=15768000;

  # OCSP Stapling - fetch OCSP records from URL in ssl_certificate and cache them
  ssl_stapling on;
  ssl_stapling_verify on;

  # Verify chain of trust of OCSP response using Root CA and Intermediate certs
  ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

  # Cloudflare DNS

  # Required for LE certificate enrollment using certbot
  location '/.well-known/acme-challenge' {
    default_type "text/plain";
    root /var/www/html;

  location / {
    proxy_pass http://localhost:8000;
    proxy_redirect http:// $scheme://;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Host $http_host;

Customizing the UI

There are a number of settings that let you customize the appearance of the website without changing the code.

para.fixed_nav = false
para.show_branding = true
para.logo_url = "/logo.svg"
para.logo_width = 90
para.stylesheet_url = "/style.css"

Alternatively, clone this repository and edit the following:

  • HTML templates are in src/main/resources/templates/
  • CSS stylesheets can be found in src/main/resources/static/styles/
  • JavaScript files can be found in src/main/resources/static/scripts
  • Images are in located in src/main/resources/static/images/

Also, please refer to the documentation for Spring Boot and Spring MVC.

Translating Scoold

You can translate Scoold to your language by copying the English language file and translating it. When you're done, change the file name from "" to "" where "xx" is the language code for your locale. Finally, open a pull request here.

Language File Progress
Albanian 0%
Arabic ✔️ (Google Translate)
Belarusian 0%
Bulgarian ✔️
Catalan 0%
Chinese (Traditional) ✔️ Thanks Kyon Cheng!
Chinese (Simplified) ✔️ Thanks Kyon Cheng!
Croatian 0%
Czech 0%
Danish ✔️ Thanks @viking1972!
Dutch ✔️ Thanks Jan Halsema!
English ✔️
Estonian 0%
Finnish 0%
French ✔️ Thanks Charles Maheu!
German ✔️ Thanks Patrick Gäckle!
Greek 0%
Hebrew 0%
Hindi ✔️ Thanks Rakesh Gopathi!
Hungarian 0%
Icelandic 0%
Indonesian 0%
Irish 0%
Italian 0%
Japanese ✔️ Thanks Mozy Okubo!
Korean ✔️ Thanks HyunWoo Jo!
Lithuanian 0%
Latvian 0%
Macedonian 0%
Malay 0%
Maltese 0%
Norwegian 0%
Polish 0%
Portuguese 0%
Romanian 0%
Russian 0%
Serbian 0%
Slovak 0%
Slovenian 0%
Spanish ✔️ Thanks Trisha Jariwala!
Swedish 0%
Thai 0%
Turkish ✔️ Thanks Aysad Kozanoglu!
Ukrainian 0%
Vietnamese 0%

Building Scoold

To compile it you'll need JDK 8+ and Maven. Once you have it, just clone and build:

$ git clone && cd scoold
$ mvn install

To run a local instance of Scoold for development, use:

$ mvn -Dconfig.file=./application.conf spring-boot:run


You can get support here by submitting an issue. Also you can head over to the Gitter chat room for help. Issues related to Scoold Pro must be reported to Erudika/scoold-pro. Paid/priority support is also available.


  1. Fork this repository and clone the fork to your machine
  2. Create a branch (git checkout -b my-new-feature)
  3. Implement a new feature or fix a bug and add some tests
  4. Commit your changes (git commit -am 'Added a new feature')
  5. Push the branch to your fork on GitHub (git push origin my-new-feature)
  6. Create new Pull Request from your fork

Please try to respect the code style of this project. To check your code, run it through the style checker:

mvn validate

For more information see

Square Face


Apache 2.0