diff --git a/commands.py b/commands.py
index c2119db..20d498b 100644
--- a/commands.py
+++ b/commands.py
@@ -42,7 +42,7 @@ async def about_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> N
         f"{context.bot.first_name} is an inline image grabber written in python that grabs images from Danbooru "
         f"(or other similar services).\n\n"
         f"{html_parser.bold("currently configured instance:")}\n"
-        f"{html_parser.italic(config.get('Service', 'Name'))}  ({config.get('Service', 'Domain')})",
+        f"{html_parser.italic(config.get('App', 'Name'))}  ({config.get('App', 'Host')})",
         parse_mode=ParseMode.HTML,
         reply_markup=reply_markup
     )
diff --git a/config.ini b/config.ini
index cfde3e4..e06a7be 100644
--- a/config.ini
+++ b/config.ini
@@ -1,8 +1,17 @@
 [General]
+; HTTP API token of Telegram bot.
+; Can also be set with the BOT_TOKEN environment variable.
 Token =
+; (Optional) URL for "source code" button in /about.
+; If not set, button will not appear in "about" menu.
 SourceUrl =
 
-[Service]
+[App]
+; Application name (e.g. Danbooru).
 Name = Danbooru
-Domain = danbooru.donmai.us
-PublicDomain = danbooru.donmai.us
\ No newline at end of file
+; Host (without http://) used to access the application API.
+Host = danbooru.donmai.us
+; (Optional) Public host name (without http://) for the “Open in [App.Name]” button.
+; Useful if the bot is hosted on the same server as the application.
+; If not set, [App.Host] will be used instead.
+HostName =
\ No newline at end of file
diff --git a/inline_query.py b/inline_query.py
index 65b1cfb..c940ad7 100644
--- a/inline_query.py
+++ b/inline_query.py
@@ -21,7 +21,7 @@ async def inline_query(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
         return
 
     from main import config
-    response = requests.get(f"http://{config.get('Service', 'Domain')}/posts/{query}.json")
+    response = requests.get(f"http://{config.get('App', 'Host')}/posts/{query}.json")
 
     if response.status_code != 200:
         await invalid_query(update, query)
@@ -38,10 +38,12 @@ async def answer_query(update: Update, query: str,
     copyrights = humanize_tags_from_json(data['tag_string_copyright'], "unknown copyright")
     artists = humanize_tags_from_json(data['tag_string_artist'], "unknown artist")
     rating = format_rating(data['rating'])
+    hostname = config.get('App', 'HostName')
+    hostname = hostname if hostname != "" else config.get('App', 'Host')
     keyboard = [
         [
-            InlineKeyboardButton(f"Open in {config.get('Service', 'Name')}",
-                                 url=f"https://{config.get('Service', 'PublicDomain')}/posts/{query}"),
+            InlineKeyboardButton(f"Open in {config.get('App', 'Name')}",
+                                 url=f"https://{hostname}/posts/{query}"),
             InlineKeyboardButton("View original", url=data['file_url'])
         ]
     ]
diff --git a/main.py b/main.py
index caa22e1..9d7f581 100644
--- a/main.py
+++ b/main.py
@@ -34,14 +34,13 @@ def main() -> None:
 
 
 def validate_config() -> None:
-    # TODO: do some PublicDomain checks or something
     # noinspection PyBroadException
     try:
-        response = requests.get(f"http://{config.get('Service', 'Domain')}/status.json")
+        response = requests.get(f"http://{config.get('App', 'Host')}/status.json")
         if response.status_code != 200:
             raise
     except:
-        print("Unable validate Domain in config.ini.")
+        print("Unable validate App.Host in config.ini.")
         exit(1)
 
 
@@ -52,7 +51,7 @@ def get_token():
     if config.get('General', 'Token') != "":
         return config.get('General', 'Token')
 
-    print("Set BOT_TOKEN environment variable or use config.ini to set bot token.")
+    print("Set BOT_TOKEN environment variable or use General.Token in config.ini to set bot token.")
     exit(1)