This is a very simple, open source, real time messaging system. It does not save the messages anywhere, being designed to be used on churches or venues, by volunteers (with access control), to send alerts or messages to a big screen. I designed it to be used specifically on my local church. Feel free to use it wherever you want.
- For now this app is only available in Portuguese (BR) due to time restrictions
- English will be available some time in the future, maybe.
Even though I did my due diligence to secure the connections, communication and access control, this app security has NOT been properly tested, please do NOT use it to send sensitive data anywhere. You've been warned.
This app has 3 parts:
Also known as the display client. This is where the management happens, this app controls what messages can be sent (channels). Defines when the message content is valid, define dynamic fields and control user access. It is also responsible to enqueue and display the received messages (which are on memory only and not stored anywhere). Open the configuration panel to define properties such as the server API and Web App URL
It's a hidden layer that houses the simple, file-based database and API endpoints. It also manages the WebSocket connections to the display client (the windows app). Forwarding any new messages to the appropriate clients
It's a Blazor WASM PWA web page, it first must get access to a channel by reading the "user" QR Code on the windows display client, then the app connects to the API to get the channel's field data and then it is able to send messages when the windows display client is also running.
The Windows client app can be downloaded on the Releases page. Just unzip the client and you're ready to go. Open the client and set the API and App URLs on the configuration panel, then create a new channel, set the fields then invite the users to the channel.
The backend API and Web App (front-end) must be deployed on a server, with a reverse proxy configured with SSL. see the Deployment section below for details
Courier notifications need two containers running, one serves the front-end web assembly app, the other is the backend API.
I highly recommend using a subdomain for this app. in this readme, I'll use courier
When deploying, use nginx or any other reverse proxy to redirect the services like this:
https://courier.your-domain.com/
-> to the frontend service (http port 5091)https://courier.your-domain.com/api
-> to the backend service (http port 5090)
Don't forget to enable WebSocket support on your proxy.
The front and back-end reverse proxy MUST have SSL configured to enable saving the web app as a PWA on the user's phone.
You can do this easily on your reverse proxy if you have a domain. Search for let's encrypt
for more info
Use the following docker compose file to deploy the backend and frontend images. Modify the environment variables as needed
services:
courier-backend:
image: leocb/cn-server:latest
container_name: courier-backend
environment:
- CORS_HOSTNAME=https://courier.your-domain.com #Enable CORS protection on the API. set this to your front-end URI
- ENABLE_SWAGGER=false #Set true if you want to explore the endpoints, access via https://courier.your-domain.com/swagger
volumes:
- /path/to/database:/database
ports:
- 5090:8080 # HTTP port host:container
restart: unless-stopped
# This container is not compatible with cloudflare tunnels (don't know why)
# The most easy alternative is to use Cloudflare pages (instructions down below).
# If you'll use cloudflare pages to publish the front-end, remove the following service from this compose file:
courier-frontend:
image: leocb/cn-web-app:latest
container_name: courier-frontend
volumes:
- /path/to/appsettings.json:/usr/share/nginx/html/appsettings.json # the contents of this file are listed below
ports:
- 5091:80 # HTTP port host:container
restart: unless-stopped
## Front-end config file content (remove the #'s):
#{
# "ApiHostname": "https://courier.your-domain.com/"
#}
Create a file named appsettings.json
and save it somewhere on your local machine, then in the docker compose file above, specify where this file is. here's the content for the file, modify where needed:
{
"ApiHostname": "https://courier.your-domain.com/"
}
Now configure your reverse proxy like this
https://courier.your-domain.com/
-> to the frontend service (http port 5091)https://courier.your-domain.com/api
-> to the backend service (http port 5090).
Don't forget to enable WebSocket support for the backend proxy!
Open the display client on windows, configure the backend URI
Finally, go to courier.your-domain.com on your phone, follow the instructions and enjoy!
This is an excerpt from This tutorial, always check it for the most up-to-date info
- Log in to the Cloudflare dashboard ↗ and select your account.
- In Account Home, select Workers & Pages.
- Select Create > Pages > Connect to Git.
Select the new GitHub repository that you created and, in the Set up builds and deployments section, provide the following information:
⚠️ Warning: Notice that the build command below includes the API URI and it's different from the front-end sub domain (namely it'scourier-api
), this is because when using the Cloudflare pages, it's not possible to use the same sub-domain for both the back and front-end, since you can't customize the reverse proxy. Use the API on another sub domain instead and you should be fine!
Configuration option | Value |
---|---|
Production branch | latest |
Build command | chmod +x CN.Web.App/build.sh && ./CN.Web.App/build.sh courier-api.your-domain.com |
Build directory | CN.Web.App/publish/wwwroot |
After configuring your site, you can begin your first deploy. You should see Cloudflare Pages installing dotnet
, your project dependencies, and building your site, before deploying it.
After deploying your site, you will receive a unique subdomain for your project on *.pages.dev
. Every time you commit new code to your Blazor site, Cloudflare Pages will automatically rebuild your project and deploy it.
The following section has some details needed to properly develop and Build/Publish the project.
To develop the solution, simply use visual studio (2022 or later) and open the .sln
file
The backend is a ASP.NET project and runs with the kestrel web server, meaning a simple publish action on VS is enough.
The frontend is just a bunch of static files that need a static file server to work. We use nginx and build it using docker. See here. The front-end can also be deployed using Cloudflare pages.
The Desktop app is a classic C# .NET WPF app. build the release and zip the results to redistribute.
Note: the front-end docker image does not work when using Cloudflare tunnels (don't ask me why), you can use Cloudflare pages instead.
In a command line, Open the CN.Web.App
folder
Run dotnet publish -c Release -o ./publish
Run docker build -t [username]/cn-web-app .
To test locally, Run docker run -it --rm -d -p 8080:80 --name courier-frontend [username]cn-web-app
Push to docker: docker image push [username]/cn-web-app
When publishing the docker images, pay special attention to a bug on VS tooling - Relevant bug reports: here and here
- Right click the
CN.Server
project and selectPublish
- Select or Create a new profile
- If Creating: Select
Docker Container Registry
as the target - Select
Docker Hub
on the specific target - Fill in your username and password
- Select
.NET SDK
on the container build - Finish
- Edit the generated "publish profile file" and remove your username from the url
- If Creating: Select
- With the profile selected, Click on the
Publish
button on the top right - The output will say "Publish Completed", but in fact it was not!
- Copy the last command before the success messages
- Open the windows power shell terminal and paste the command
- Modify the
--repository
argument and add your docker hubusername
and a/
and execute the command. The image should be uploaded properly now. - The command should look something like this
dotnet "C:\Program Files\dotnet\sdk\8.0.200\Containers\build\..\containerize\containerize.dll" D:\Code\Courier-Notifications\CN.Server\obj\Release\net8.0\linux-x64\PubTmp\Out --baseregistry mcr.microsoft.com --baseimagename dotnet/aspnet --repository leocb/cn-server --workingdirectory /app --baseimagetag 8.0 --outputregistry registry.hub.docker.com --appcommand dotnet CN.Server.dll --labels org.opencontainers.image.created=2024-07-03T03:55:20.7131052Z org.opencontainers.artifact.created=2024-07-03T03:55:20.7131052Z org.opencontainers.image.authors=leocb org.opencontainers.image.version=1.0.0 "org.opencontainers.image.title=Courier Notifications Server" org.opencontainers.image.base.name=mcr.microsoft.com/dotnet/aspnet:8.0 --imagetags latest --rid linux-x64 --ridgraphpath "C:\Program Files\dotnet\sdk\8.0.200/PortableRuntimeIdentifierGraph.json"