diff --git a/.env b/.env
index 05ef05e..7a0f6d6 100644
--- a/.env
+++ b/.env
@@ -46,7 +46,7 @@ LOCK_DSN=flock
###< symfony/lock ###
###> symfony/mailer ###
-# MAILER_DSN=null://null
+MAILER_DSN=null://null
###< symfony/mailer ###
###> symfony/messenger ###
@@ -60,6 +60,7 @@ MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
MAILER_SENDER_NAME="Domain Watchdog"
MAILER_SENDER_EMAIL=notifications@example.com
REGISTRATION_ENABLED=true
+REGISTRATION_VERIFY_EMAIL=false
OAUTH_CLIENT_ID=
OAUTH_CLIENT_SECRET=
OAUTH_AUTHORIZATION_URL=
diff --git a/README.md b/README.md
index d745d3d..dc116c5 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,11 @@

Domain Watchdog
-Your companion in the quest for domain namesdomainwatchdog.eu »
+Your companion in the quest for domain names
domainwatchdog.eu »
Domain Watchdog is a standalone application that utilizes RDAP to gather publicly accessible information about domain
-names, track their history, and automatically purchase them. For more information please check [the wiki](https://github.com/maelgangloff/domain-watchdog/wiki) !
+names, track their history, and automatically purchase them. For more information please
+check [the wiki](https://github.com/maelgangloff/domain-watchdog/wiki) !
## Why use it?
@@ -25,17 +26,20 @@ detailed history of events (ownership changes, renewals, etc.) is not feasible w
### Docker Deployment
1. Clone the repository
-2. Build the Docker image locally
+2. Modify environment variables (.env) and add static files to customize your instance (see [INSTALL.md](/INSTALL.md))
+3. Pull the latest version of the Domain Watchdog image from Docker Hub.
```shell
- docker compose -f compose.yaml -f compose.prod.yaml build --pull --no-cache
+ docker compose pull
```
-3. Modify environment variables and add static files to customize your instance
-4. Start the project in production environment
+4. Start the project in production environment. If you want, you can also build the Docker image to use yourself.
```shell
- docker compose -f compose.yaml -f compose.prod.yaml up
+ docker compose up
```
-## How it works?
+By default, the container listens on http://localhost:8080, but you can configure this in environment variables.
+See the [Docker Compose file](./docker-compose.yml).
+
+## Features
### RDAP search
@@ -46,9 +50,9 @@ ICANN launched a global vote in 2023 to propose replacing the WHOIS protocol wit
registrars will no longer be required to support WHOIS from 2025 (*WHOIS Sunset Date*).[^2]
Domain Watchdog uses the RDAP protocol, which will soon be the new standard for retrieving information concerning domain
-names. The data is organized in a SQL database to minimize space by ensuring an entity is not repeated.
+names.
-### Connector Provider
+### Auto-purchase domain
A connector is a way to order a domain name. It is important to mention that this project does not act as a payment
intermediary.
@@ -63,24 +67,19 @@ The table below lists the supported API connector providers:
| GANDI | https://api.gandi.net/docs/domains/ | **Yes** |
| NAMECHEAP | https://www.namecheap.com/support/api/methods/domains/create/ | |
-### Watchlist
+If a domain has expired and a connector is linked to the Watchlist, then Domain Watchdog will try to order it via the
+connector provider's API.
+
+Note: If the same domain name is present on several Watchlists, it is not possible to predict in advance which user will
+win the domain name. The choice is left to chance.
+
+### Monitoring
A watchlist is a list of domain names, triggers and possibly an API connector.
They allow you to follow the life of the listed domain names and send you a notification when a change has been
detected.
-
-If a domain has expired and a connector is linked to the Watchlist, then Domain Watchdog will try to order it via the
-connector provider's API.
-
-Note: If the same domain name is present on several Watchlists, on the same principle as the raise condition, it is not
-possible to predict in advance which user will win the domain name. The choice is left to chance.
-
-## Useful documentation
-
-> [!NOTE]
-> - [RFC 7482 : Registration Data Access Protocol (RDAP) Query Format](https://datatracker.ietf.org/doc/html/rfc7482)
-> - [RFC 7483 : JSON Responses for the Registration Data Access Protocol (RDAP)](https://datatracker.ietf.org/doc/html/rfc7483)
-> - [RFC 7484 : Finding the Authoritative Registration Data (RDAP) Service](https://datatracker.ietf.org/doc/html/rfc7484)
+A notification to the user is sent when a new event occurs on one of the domain names in the Watchlist. This can be an
+email or a chat via Webhook. An iCalendar export of events is possible.
## Disclaimer
@@ -92,6 +91,13 @@ possible to predict in advance which user will win the domain name. The choice i
> * The project installers are responsible for the use of their own instance.
> * In no event the owner of this project will not be held responsible for other instances over which he has no control.
+## Useful documentation
+
+> [!NOTE]
+> - [RFC 7482 : Registration Data Access Protocol (RDAP) Query Format](https://datatracker.ietf.org/doc/html/rfc7482)
+> - [RFC 7483 : JSON Responses for the Registration Data Access Protocol (RDAP)](https://datatracker.ietf.org/doc/html/rfc7483)
+> - [RFC 7484 : Finding the Authoritative Registration Data (RDAP) Service](https://datatracker.ietf.org/doc/html/rfc7484)
+
## Licensing
This source code of this project is licensed under *GNU Affero General Public License v3.0 or later*.
diff --git a/compose.override.yaml b/compose.override.yaml
deleted file mode 100644
index dca2286..0000000
--- a/compose.override.yaml
+++ /dev/null
@@ -1,37 +0,0 @@
-# Development environment override
-services:
- php:
- build:
- context: .
- target: frankenphp_dev
- volumes:
- - ./:/app
- - ./frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro
- - ./frankenphp/conf.d/20-app.dev.ini:/usr/local/etc/php/app.conf.d/20-app.dev.ini:ro
- # If you develop on Mac or Windows you can remove the vendor/ directory
- # from the bind-mount for better performance by enabling the next line:
- #- /app/vendor
- environment:
- # See https://xdebug.org/docs/all_settings#mode
- XDEBUG_MODE: "${XDEBUG_MODE:-off}"
- extra_hosts:
- # Ensure that host.docker.internal is correctly defined on Linux
- - host.docker.internal:host-gateway
- tty: true
-
-###> doctrine/doctrine-bundle ###
- database:
- ports:
- - "5432"
-###< doctrine/doctrine-bundle ###
-
-###> symfony/mailer ###
- mailer:
- image: axllent/mailpit
- ports:
- - "1025"
- - "8025"
- environment:
- MP_SMTP_AUTH_ACCEPT_ANY: 1
- MP_SMTP_AUTH_ALLOW_INSECURE: 1
-###< symfony/mailer ###
diff --git a/compose.prod.yaml b/compose.prod.yaml
deleted file mode 100644
index 5c953b8..0000000
--- a/compose.prod.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-# Production environment override
-services:
- php:
- build:
- context: .
- target: frankenphp_prod
- environment:
- APP_SECRET: ${APP_SECRET}
-
- php-worker:
- build:
- context: .
- target: frankenphp_prod
- restart: always
- command: php /app/bin/console messenger:consume --all --time-limit=3600 -vvv
- environment:
- DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@database:5432/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8}
-
diff --git a/compose.yaml b/compose.yaml
deleted file mode 100644
index 564654c..0000000
--- a/compose.yaml
+++ /dev/null
@@ -1,53 +0,0 @@
-services:
- php:
- image: ${IMAGES_PREFIX:-}app-php
- restart: unless-stopped
- environment:
- SERVER_NAME: ${SERVER_NAME:-localhost}, php:80
- # Run "composer require symfony/orm-pack" to install and configure Doctrine ORM
- DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@database:5432/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8}
- # The two next lines can be removed after initial installation
- SYMFONY_VERSION: ${SYMFONY_VERSION:-}
- STABILITY: ${STABILITY:-stable}
- volumes:
- - caddy_data:/data
- - caddy_config:/config
- ports:
- # HTTP
- - target: 80
- published: ${HTTP_PORT:-80}
- protocol: tcp
- # HTTPS
- - target: 443
- published: ${HTTPS_PORT:-443}
- protocol: tcp
- # HTTP/3
- - target: 443
- published: ${HTTP3_PORT:-443}
- protocol: udp
-
-###> doctrine/doctrine-bundle ###
- database:
- image: postgres:${POSTGRES_VERSION:-16}-alpine
- environment:
- POSTGRES_DB: ${POSTGRES_DB:-app}
- # You should definitely change the password in production
- POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
- POSTGRES_USER: ${POSTGRES_USER:-app}
- healthcheck:
- test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}"]
- timeout: 5s
- retries: 5
- start_period: 60s
- volumes:
- - database_data:/var/lib/postgresql/data:rw
- # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
- # - ./docker/db/data:/var/lib/postgresql/data:rw
-###< doctrine/doctrine-bundle ###
-
-volumes:
- caddy_data:
- caddy_config:
-###> doctrine/doctrine-bundle ###
- database_data:
-###< doctrine/doctrine-bundle ###
diff --git a/config/services.yaml b/config/services.yaml
index fd5f9ad..c7deee0 100644
--- a/config/services.yaml
+++ b/config/services.yaml
@@ -8,6 +8,7 @@ parameters:
mailer_sender_name: '%env(string:MAILER_SENDER_NAME)%'
oauth_enabled: '%env(OAUTH_CLIENT_ID)%'
registration_enabled: '%env(bool:REGISTRATION_ENABLED)%'
+ registration_verify_email: '%env(bool:REGISTRATION_VERIFY_EMAIL)%'
limited_features: '%env(bool:LIMITED_FEATURES)%'
limit_max_watchlist: '%env(int:LIMIT_MAX_WATCHLIST)%'
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..1ec9b7b
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,49 @@
+# Please see https://github.com/maelgangloff/domain-watchdog
+services:
+ domainwatchdog:
+ image: maelgangloff/domain-watchdog:latest
+ restart: unless-stopped
+ environment:
+ SERVER_NAME: http://${SERVER_NAME:-localhost}
+ DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@${POSTGRES_HOST:-database}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8}
+ APP_SECRET: ${APP_SECRET:-ChangeMe}
+ REGISTRATION_ENABLED: ${REGISTRATION_ENABLED:-true}
+ REGISTRATION_VERIFY_EMAIL: ${REGISTRATION_ENABLED:-false}
+ LIMITED_FEATURES: ${LIMITED_FEATURES:-false}
+ LIMIT_MAX_WATCHLIST: ${LIMIT_MAX_WATCHLIST:-0}
+ LIMIT_MAX_WATCHLIST_DOMAINS: ${LIMIT_MAX_WATCHLIST_DOMAINS:-0}
+ MAILER_DSN: ${MAILER_DSN:-null://null}
+ volumes:
+ - caddy_data:/data
+ - caddy_config:/config
+ - ./public/content:/app/public/content
+ ports:
+ - 127.0.0.1:8080:80
+
+ php-worker:
+ image: maelgangloff/domain-watchdog:latest
+ restart: always
+ command: php /app/bin/console messenger:consume --all --time-limit=3600 -vvv
+ environment:
+ DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@${POSTGRES_HOST:-database}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8}
+ APP_SECRET: ${APP_SECRET:-ChangeMe}
+ MAILER_DSN: ${MAILER_DSN:-null://null}
+
+ database:
+ image: postgres:${POSTGRES_VERSION:-16}-alpine
+ environment:
+ POSTGRES_DB: ${POSTGRES_DB:-app}
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
+ POSTGRES_USER: ${POSTGRES_USER:-app}
+ healthcheck:
+ test: [ "CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}" ]
+ timeout: 5s
+ retries: 5
+ start_period: 60s
+ volumes:
+ - database_data:/var/lib/postgresql/data:rw
+
+volumes:
+ caddy_data:
+ caddy_config:
+ database_data:
diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php
index 1b44baf..e5a95cb 100644
--- a/src/Controller/RegistrationController.php
+++ b/src/Controller/RegistrationController.php
@@ -75,6 +75,25 @@ class RegistrationController extends AbstractController
)
);
+ if (false === (bool) $this->getParameter('registration_verify_email')) {
+ $user->setVerified(true);
+ } else {
+ $email = $this->emailVerifier->sendEmailConfirmation('app_verify_email', $user,
+ (new TemplatedEmail())
+ ->from(new Address($this->mailerSenderEmail, $this->mailerSenderName))
+ ->to($user->getEmail())
+ ->locale('en')
+ ->subject('Please Confirm your Email')
+ ->htmlTemplate('emails/success/confirmation_email.html.twig')
+ );
+
+ $signedUrl = (string) $email->getContext()['signedUrl'];
+ $this->logger->notice('The validation link for user {username} is {signedUrl}', [
+ 'username' => $user->getUserIdentifier(),
+ 'signedUrl' => $signedUrl,
+ ]);
+ }
+
$this->em->persist($user);
$this->em->flush();
@@ -82,21 +101,6 @@ class RegistrationController extends AbstractController
'username' => $user->getUserIdentifier(),
]);
- $email = $this->emailVerifier->sendEmailConfirmation('app_verify_email', $user,
- (new TemplatedEmail())
- ->from(new Address($this->mailerSenderEmail, $this->mailerSenderName))
- ->to($user->getEmail())
- ->locale('en')
- ->subject('Please Confirm your Email')
- ->htmlTemplate('emails/success/confirmation_email.html.twig')
- );
-
- $signedUrl = (string) $email->getContext()['signedUrl'];
- $this->logger->notice('The validation link for user {username} is {signedUrl}', [
- 'username' => $user->getUserIdentifier(),
- 'signedUrl' => $signedUrl,
- ]);
-
return new Response(null, 201);
}