diff --git a/docs/configuration.md b/docs/configuration.md
index f94454b84d036646be72250795342b373e8c0d52..2eee94e6c7a7f2241f0d343d15331a2bae93c0b3 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -71,6 +71,8 @@ $ node renovate --help
 
     -h, --help                           output usage information
     --enabled [boolean]                  Enable or disable renovate
+    --log-file <string>                  Log file path
+    --log-file-level <string>            Log file log level
     --onboarding [boolean]               Require a Configuration PR first
     --platform <string>                  Platform type of repository
     --endpoint <string>                  Custom endpoint to use
@@ -134,6 +136,8 @@ Obviously, you can't set repository or package file location with this method.
 | Name | Description | Type | Default value | Environment | CLI |
 |------|-------------|------|---------------|-------------|-----|
 | `enabled` | Enable or disable renovate | boolean | `true` | `RENOVATE_ENABLED` | `--enabled` |
+| `logFile` | Log file path | string | `null` | `RENOVATE_LOG_FILE` | `--log-file` |
+| `logFileLevel` | Log file log level | string | `"debug"` | `RENOVATE_LOG_FILE_LEVEL` | `--log-file-level` |
 | `onboarding` | Require a Configuration PR first | boolean | `true` | `RENOVATE_ONBOARDING` | `--onboarding` |
 | `platform` | Platform type of repository | string | `"github"` | `RENOVATE_PLATFORM` | `--platform` |
 | `endpoint` | Custom endpoint to use | string | `null` | `RENOVATE_ENDPOINT` | `--endpoint` |
@@ -157,7 +161,7 @@ Obviously, you can't set repository or package file location with this method.
 | `branchName` | Branch name template | string | `"renovate/{{depName}}-{{newVersionMajor}}.x"` | `RENOVATE_BRANCH_NAME` |  |
 | `commitMessage` | Commit message template | string | `"Update dependency {{depName}} to version {{newVersion}}"` | `RENOVATE_COMMIT_MESSAGE` |  |
 | `prTitle` | Pull Request title template | string | `"{{#if isPin}}Pin{{else}}Update{{/if}} dependency {{depName}} to version {{#if isRange}}{{newVersion}}{{else}}{{#if isMajor}}{{newVersionMajor}}.x{{else}}{{newVersion}}{{/if}}{{/if}}"` | `RENOVATE_PR_TITLE` |  |
-| `prBody` | Pull Request body template | string | `"This Pull Request updates dependency {{depName}} from version `{{currentVersion}}` to `{{newVersion}}`\n\n{{changelog}}"` | `RENOVATE_PR_BODY` |  |
+| `prBody` | Pull Request body template | string | `"This {{#if isGitHub}}Pull{{else}}Merge{{/if}} Request updates dependency [{{depName}}]({{repositoryUrl}}) from version `{{currentVersion}}` to `{{newVersion}}`\n{{#if releases.length}}\n\n### Commits\n\n<details>\n<summary>{{githubName}}</summary>\n\n{{#each releases as |release|}}\n#### {{release.version}}\n{{#each release.commits as |commit|}}\n-   [`{{commit.shortSha}}`]({{commit.url}}){{commit.message}}\n{{/each}}\n{{/each}}\n\n</details>\n{{/if}}\n<br />\n\nThis {{#if isGitHub}}PR{{else}}MR{{/if}} has been generated by [Renovate Bot](https://keylocation.sg/our-tech/renovate)."` | `RENOVATE_PR_BODY` |  |
 | `yarnCacheFolder` | Location of yarn cache folder to use. Set to empty string to disable | string | `"/tmp/yarn-cache"` | `RENOVATE_YARN_CACHE_FOLDER` | `--yarn-cache-folder` |
 | `maintainYarnLock` | Keep yarn.lock files updated in base branch | boolean | `false` | `RENOVATE_MAINTAIN_YARN_LOCK` | `--maintain-yarn-lock` |
 | `yarnMaintenanceBranchName` | Branch name template when maintaining yarn.lock | string | `"renovate/yarn-lock"` | `RENOVATE_YARN_MAINTENANCE_BRANCH_NAME` |  |
@@ -170,7 +174,7 @@ Obviously, you can't set repository or package file location with this method.
 | `groupBranchName` | Branch name template for the group | string | `"renovate/{{groupSlug}}"` | `RENOVATE_GROUP_BRANCH_NAME` |  |
 | `groupCommitMessage` | Group commit message | string | `"Renovate {{groupName}} packages"` | `RENOVATE_GROUP_COMMIT_MESSAGE` |  |
 | `groupPrTitle` | Pull Request title template for the group | string | `"Renovate {{groupName}} packages"` | `RENOVATE_GROUP_PR_TITLE` |  |
-| `groupPrBody` | Pull Request body template for the group | string | `"This PR renovates the package group \"{{groupName}}\"."` | `RENOVATE_GROUP_PR_BODY` |  |
+| `groupPrBody` | Pull Request body template for the group | string | `"This {{#if isGitHub}}Pull{{else}}Merge{{/if}} Request renovates the package group \"{{groupName}}\".\n\n{{#each upgrades as |upgrade|}}\n-   [{{upgrade.depName}}]({{upgrade.repositoryUrl}}): from `{{upgrade.currentVersion}}` to `{{upgrade.newVersion}}`\n{{/each}}\n\n### Commits\n\n{{#each upgrades as |upgrade|}}\n{{#if upgrade.releases.length}}\n<details>\n<summary>{{upgrade.githubName}}</summary>\n{{#each upgrade.releases as |release|}}\n\n#### {{release.version}}\n{{#each release.commits as |commit|}}\n-   [`{{commit.shortSha}}`]({{commit.url}}){{commit.message}}\n{{/each}}\n{{/each}}\n\n</details>\n{{/if}}\n{{/each}}\n\n<br />\n\nThis {{#if isGitHub}}PR{{else}}MR{{/if}} has been generated by [Renovate Bot](https://keylocation.sg/our-tech/renovate)."` | `RENOVATE_GROUP_PR_BODY` |  |
 | `labels` | Labels to add to Pull Request | list | `[]` | `RENOVATE_LABELS` | `--labels` |
 | `assignees` | Assignees for Pull Request | list | `[]` | `RENOVATE_ASSIGNEES` | `--assignees` |
 | `reviewers` | Requested reviewers for Pull Requests (GitHub only) | list | `[]` | `RENOVATE_REVIEWERS` | `--reviewers` |
diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index e1379b59c0d7824b349fcd83d6747aba02a69981..7e69e6b2f3ffa782e8a83df59ca37d91c67afb7c 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -22,6 +22,17 @@ const options = [
     description: 'Enable or disable renovate',
     type: 'boolean',
   },
+  {
+    name: 'logFile',
+    description: 'Log file path',
+    type: 'string',
+  },
+  {
+    name: 'logFileLevel',
+    description: 'Log file log level',
+    type: 'string',
+    default: 'debug',
+  },
   {
     name: 'onboarding',
     description: 'Require a Configuration PR first',
diff --git a/lib/config/index.js b/lib/config/index.js
index 9cba4ca2b5ad8f249cf2d3a4233931e94ad4a064..4e182faefbd7a31b6a2a66309fee8b3652bee98a 100644
--- a/lib/config/index.js
+++ b/lib/config/index.js
@@ -32,6 +32,18 @@ async function parseConfigs(env, argv) {
   // Set log level
   logger.levels('stdout', config.logLevel);
 
+  // Add file logger
+  if (config.logFile) {
+    logger.debug(
+      `Enabling ${config.logFileLevel} logging to ${config.logFile}`
+    );
+    logger.addStream({
+      name: 'logfile',
+      path: config.logFile,
+      level: config.logFileLevel,
+    });
+  }
+
   logger.debug(`Default config = ${redact(defaultConfig)}`);
   logger.debug(`File config = ${redact(fileConfig)}`);
   logger.debug(`CLI config: ${redact(cliConfig)}`);
@@ -122,6 +134,9 @@ async function parseConfigs(env, argv) {
 
   // Print config
   logger.debug(`config=${redact(config)}`);
+  // Remove log file entries
+  delete config.logFile;
+  delete config.logFileLevel;
 }
 
 function getCascadedConfig(repo, packageFile) {