An article sharing website developed by Go.
Here is a live demo: inews (hosting on AWS EC2 with Load Balancer, Route 53, SES, Certificate Manager.)
The website has been closed due to the cost of maintenance being too high. See the Demo section at the end of the README.
I choose gin as the backend web framework for its simplicity and high performance (it is also the most popular framework in Go, see Top Go Web Frameworks).
For database ORM, I choose gorm. It is a full-featured ORM with great community support and easy to follow documentation.
Besides, if you choose sqlite
as the database driver, then you can get rid of the setting database burden (the data will be stored in a file tmp.db
in the root of project) and focus on the backend development.
If you are a novice to the database with no idea about the many-to-many relationship, the databases/bookmark.go
is a good example. I utilize many-to-many relationship to implement features such as searching articles with tags and bookmarking articles.
The following diagram illustrates the architecture I built on AWS:
│
▼
┌─────────────────────────────────────────────┐
│ ALB (application load balancer, layer 7) │
└─────────────────────────────────────────────┘
│
┌───────────────────────────────────────────────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐ ┌───────────────────────────┐
│ Listener (HTTP, port80) │ │ Listener (HTTPS, port443) │ │ Listener │
└───────────────────────────┘ └───────────────────────────┘ └───────────────────────────┘
│ │ │
▼ ▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐ ┌───────────────────────────┐
│ Target Group (dev) │ │ Target Group (prod) │ │ Target Group (other) │
│ ┌───────────────────────┐ │ │ ┌───────────────────────┐ │ │ │
│ │ EC2 (Testing, AZ #1) │ │ │ | EC2 (AZ #1) │ │ │ │
│ └───────────────────────┘ │ │ └───────────────────────┘ │ │ ..... │
│ ┌───────────────────────┐ │ │ ┌───────────────────────┐ │ │ │
│ │ EC2 (Staging, AZ #1) │ │ │ │ EC2 (AZ #2) │ │ │ │
│ └───────────────────────┘ │ │ └───────────────────────┘ │ │ │
└───────────────────────────┘ └───────────────────────────┘ └───────────────────────────┘
▲ │ ▲ │
| ▼ | ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ │ │ │
│ RDS (MySQL) │ │ RDS (MySQL) │
│ │ │ │
└───────────────────────────┘ └───────────────────────────┘
The credentials are stored in config.yml
. There are some environment variables that can be overwritten (inside config/config.go
). Environment variables have a WEB_
prefix. You might want to use some of them: WEB_APP_HTTP_PORT
, WEB_APP_HTTPS_PORT
, WEB_DB_PORT
, and WEB_DB_HOST
.
The admin users are created by the following mechanism:
- Write down their emails in
config.yml
- Setup web server
- Register with these corresponding emails on the website
To send reset password emails, see the Others section.
# Set the env values if needed
# export WEB_APP_HTTP_PORT=8080
# export WEB_APP_HTTPS_PORT=8443
# export WEB_DB_PORT=3306
# export WEB_DB_HOST=127.0.0.1
go run cmd/main.go
- Build
- Development
docker build . --target builder -t cwhuang29/article-sharing-website:dev
- Production
docker build . -t cwhuang29/article-sharing-website:prod
- Run
- Database
docker run -d \
--name db \
-e MYSQL_DATABASE=inews \
-e MYSQL_ROOT_PASSWORD=a1234567 \
-e MYSQL_USER=user01 \
-e MYSQL_PASSWORD=a1234567 \
mysql:5.7.32 \
mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
- Web server
docker run -d \
--name web \
--link db:db \
-e WEB_APP_HTTP_PORT=80 \
-e WEB_APP_HTTPS_PORT=443 \
-e WEB_DB_PORT=3306 \
-e WEB_DB_HOST=db \
-e WEB_APP_URL=https://example.com \
-e WEB_EMAIL_SENDER=<sender email address> \
-e WEB_EMAIL_REGION=us-east-1
-p 80:80 \
-p 443:443 \
cwhuang29/article-sharing-website:prod
- Fill in settings in the
email
section inconfig.yml
. Sender email address and region can be overwritten by envWEB_EMAIL_SENDER
andWEB_EMAIL_REGION
respectively. app.url
is mandatory cause the reset password link is based on this value (can be overwritten byWEB_APP_URL
)email.numPerDay
andemail.numPerSec
inconfig.yml
, which represent maximum send quota/rate, is the restrictions imposed by AWS.- AWS retrieves credentials under
~/.aws/credentials
. Copy credentials from the AWS web console and create this file with the following content:
[default]
aws_access_key_id=
aws_secret_access_key=
- Verify domains and (sender) email addresses on AWS console (see here).
- Submit a request to AWS to increase sending limits and move your account out of the Amazon SES sandbox (see here).
Instead of connecting to the database container (which name is db
in my case) directly, we can run another MySQL container and query the database container.
docker run -it --rm --link db:db mysql:5.7.32 mysql -hdb -u user01 -pa1234567 inews
To dump the database, run
docker exec -it db mysqldump -u user01 -pa1234567 inews > data-`date +"%Y-%m-%d-%H-%M-%S"`.sql
There is some warning messages while dumping out data. To avoid warning, you can run:
docker exec -it db mysqldump -u user01 -pa1234567 --no-tablespaces inews <tables, seperated by space> \
grep -v "Using a password on the command line interface can be insecure" > data-`date +"%Y-%m-%d-%H-%M-%S"`.sql
Since all cookies are sent only with encrypted requests and responses, you may want to get certificates for localhost. Here is a good example: How to get HTTPS working on your local development environment in 5 minutes.
After setting up the certificates, copy server.crt
and server.key
to the certs/
folder (in the root of the project), and then connect to URL https://localhost
.
If you want to host the website on AWS EC2, run the following script to install Docker and MySQL Do note that installing docker takes about 1.5~2 GB space. You might want to create an EC2 with a larger disk space
# Install Docker
sudo yum update -y
sudo amazon-linux-extras install docker
sudo service docker start
sudo usermod -a -G docker ec2-user
# Logout and log back in
# Install MySQL
sudo yum -y install mysql
- Register
- Logout
- Modify articles
- Delete articles
- Optimize Docker builds
- Pagination
- Middleware
- CSRF token
- Support HTTPS
- Add an "only administrators can view" option
- Outline and cover photo for the overview page
- Reset password
- Login Throttling
- Tag-based search
- Preserve fetched data while going to the previous page
- Save (bookmark) button
- Like button
- Logger
- Admin overview page (e.g. show statistics)
- Security issues about uploading files
- Support CLI
- Integrate AWS SES to send emails