Media distribution without the platform markup. Home of the free/open source Rent Free Media distribution of Django + Wagtail.
This repository has been archived on 2023-05-07. You can view files and clone it, but cannot push or open issues or pull requests.
Go to file
MichaelYick 355f503b28 Remove postgresql on exit in development deploy script 2023-05-06 23:29:28 -05:00
contrib Remove postgresql on exit in development deploy script 2023-05-06 23:29:28 -05:00
docs typo 2022-08-04 11:19:15 -05:00
src Use cavemanon fork of wagtail-personalisation 2023-05-06 22:25:59 -05:00
.dockerignore Add Dockerfile + docker-compose file 2023-05-06 10:59:29 -05:00
.gitignore initial commit 2022-04-06 00:51:03 -05:00
Dockerfile Add Dockerfile + docker-compose file 2023-05-06 10:59:29 -05:00
LICENSE Create LICENSE 2022-02-26 12:22:37 -06:00
README.md Add Dockerfile + docker-compose file 2023-05-06 10:59:29 -05:00
docker-compose.yml Add Dockerfile + docker-compose file 2023-05-06 10:59:29 -05:00
mkdocs.yml Ansible docs addendum for live deployment 2022-04-06 17:08:14 -05:00

README.md

Cavemanon's fork of RentFreeMedia

RentFreeMedia is a media distribution framework built on Django and Wagtail. With it, you can publish either public or premium / subscription-based content similar to the features provided in services such as Patreon, Apple Podcasts, and Substack.

It processes subscription payments via Stripe, and in addition to serving premium content from web pages, makes authenticated RSS feeds for podcasts and premium written articles, like so...

subscribe-2

...

subscribe-3

RockForMedia is Cavemanon's fork of RentFreeMedia, tuned specifically to our needs.

Summary of Features

  • Your media distribution tools also become your brand's website. Media objects can also be embedded on your website's pages if you like.
  • Click-able block-level CSS styling: add CSS classes to individual template blocks without getting into the code for minor style adjustments.
  • The base templates are plain ole HTML and CSS. No JavaScript is required to customize your site's design, unless you want there to be.
  • Base templates use Bootstrap 5. You can customize your whole site design with a custom header, custom footer, and bootstrap.css modifications.
  • Dismissable content walls / "paywalls" if you choose to employ them, defined at the individual page level.
  • Full text site-wide search, enabled by default.
  • Customize anything by user tier. Subscription tier filters are included out of the box, and custom tier filters can be defined in python code and mixed, matched, or combined in any way you see fit.
  • Premium authenticated RSS feeds if you are publishing articles as one would do on Substack, or podcasts / video casts as one would do on Patreon, with secure links to paid subscription content.
  • RSS feeds for podcasts and video casts are configurable for most use cases. Define serial or episode-type feeds. Selectively include your promos of paid episodes... or not. Host your public episodes remotely... or not. Include your public feed combined with your paid feed for paying users... or not.
  • Write your notes and / or articles in WYSIWYG rich text or Markdown, your choice. Our customized Markdown library produces Chicago-style footnotes which work in iTunes.
  • Premium downloads are audit-able and those audits action-able. Revoke a publicly posted premium link based on download stats with a single click in the admin panel.
  • Rule-based email marketing tools, send templated email to your users by any user data you can define, without writing any code. 'Unsubscribe' links are handled automatically.
  • Stripe integration for subscription payments tied to premium content, including Stripe features like promo / coupon codes.
  • AJAX user comments, along with moderation tools, by whatever rules you choose. Host comments in your own database for only paying users, or only signed-up users, or everyone in the world.
  • Professional content collaboration tools. You can have writers who need an editor's permission to publish, and editors who need an admin's permission to publish... or none of the above... or some of the above... configure your permissions how you like them.
  • Two factor authentication, available to all users and enforceable on anyone with admin access if you choose.
  • Google analytics integration, down to the link-level. Define tracked links and buttons right in the page editor, no need to write code.
  • JSON+LD SEO schema integration done right, out of the box, automatically. Enable and define the settings and they "just work."
  • A cache based on wagtail-cache with support for all Django cache backends. Use the local disk, or Redis, or Postgres, or Memcached if you prefer. All unauthenticated requests are cached out of the box, so Google, Apple, and anonymous users won't beat up your database.

Things you will need

  1. A web host (virtual server or bare metal)
  2. A Stripe account, for payment processing
  3. An email service for invoices, user registration confirmation, and other such typical things
  4. A storage service such as Digital Ocean Spaces, AWS S3, Backblaze, etc for storing your content
  5. A laptop / desktop to run the deployment scripts on

That's it! After filling in the blanks you will be your own premium media distribution service, without the (egregious) fees of the above mentioned publishing services.

Local Development

To run the project locally:

  1. Ensure you have Python installed. This fork is developed with Python 3.11.
  2. Download and unzip the repo or a release. The "master" branch should always be stable.
  3. Edit env in the root of the src directory and provide the required settings, then save the edited file as .env. Remote storage options are not required for development mode, it will serve the media files and static files from your local machine. At minimum, specify email server info, stripe account sandbox public/private key and webhook secret, the base_url of 127.0.0.1, and the human readable site name.
  4. Make a virtual environment (python3 -m venv ~/rentfreelibs)
  5. Activate the virtual environment (~/rentfreelibs/bin/activate)
  6. Edit manage.py and set the settings target to "dev" instead of "prod"
  7. Edit website/wsgi.py and set the settings target to "dev" instead of "prod"
  8. pip install -r requirements.txt
  9. pip install django-debug-toolbar
  10. python3 manage.py makemigrations && python3 manage.py migrate
  11. python3 manage.py createsuperuser
  12. python3 manage.py runserver

You should now be up and running on http://127.0.0.1:8000

Support our Upstream!

RentFreeMedia is Free Software licensed under the AGPL for anyone to use, this repo is a fork of RentFreeMedia that we here at Cavemanon maintain. Without the work of the RentFreeMedia maintainers, we wouldn't be able to maintain our fork. Below are excerpt from the RentFreeMedia team's README page that focus on giving back to the maintainers:

Deployment

Serving content to paying customers is not trivial to do securely and robustly. Your own Nginx installation is required to do this, as each request for premium content must first be authenticated, and then fetched from storage and routed back to the user. We cache media files on the server and thus the storage service is "just storage" for the Nginx reverse proxy in front of Django to serve end users through. Media files are cached by Nginx on the server's local disk to minimize traffic between the front end and the back end.

Ansible scripts are provided in the ansible folder for automated deployment to Digital Ocean, which as a cloud service is particularly well suited to host this project because of their generous download bandwidth pricing.

If you choose to deploy the project manually, refer to the Ansible templates (ansible / includes / webserver / templates / nginx and ansible / includes / webserver / templates / systemd) for Nginx and Gunicorn configuration, sans the Ansible variables.

Let's consider the math in terms of a Digital Ocean deployment:

Presume that you have 20,000 paying customers who download your weekly (4 times a month) premium-user podcast which weighs in at 100mb for a one hour long MP3 file. Presume also that on average, each of your 20,000 paying customers downloads the episodes on three different devices.

20,000 x 3 x 4 = 240,000 downloads a month

240,000 x 100mb = 24,000,000 megabytes per month downloaded

24,000,000 mb / 1024 = 23,437 gigabytes

23,437 x $0.01 per gigabyte = $234.38

Even if we don't manage to convert the world with this project, we would hope to impress upon people that serving media is not worth 10% or 18% or 25% or 30% of your gross receipts, as other media distribution "services" seem to think by virtue of their pricing. The cloud service seems to think that it's worth $0.01 per gigabyte, and you should be looking to pay accordingly for this sort of thing.

If you use Digital Ocean, signing up with our referral link via the button below would be appreciated! You will get $100 credit as a new customer, and we'll get a referral credit after your first paid invoice.

DigitalOcean Referral Badge

Contributing

PRs are welcome! Please discuss new features you would like to see in the discussions area so that we can keep the issues forum prioritized for bug reports. The Needs / Wants thread atop the issues forum is an up-to-date list of priorities for the future.

As Wagtail is a CMS that sits on top of, in front of, Django... feature proposals should integrate with Wagtail. While it's possible to do anything in code, doing it with future maintainability in mind is also a big consideration. Would-be contributors and custom solution developers would be wise to not only thoroughly read the Wagtail docs, but also read the Wagtail code itself.

The code should work with the Django development server, with some caveats:

  • Premium media will not 'play' directly without Nginx to respond to the X-Sendfile request. You'll see 200 response codes for them in the console / logs after they successfully authenticate, though.
  • There are some complex queries in the premium media RSS feeds that only work with PostgreSQL. As of this writing SQLite and MySQL do not support distinct('field_name') and thus will not work with this distribution in production. There is an error check against the payment app views.py that will allow SQLite to work in dev mode, but you must use Postgres in production and the "subscribe" page in dev mode may have duplicate entries on SQLite.
  • The code should run fine on Linux and Mac (as well as any other BSD Unix) but I don't test against Windows, so let us know if you have any Windows issues / solutions.