Files
spring-cloud-config/spring-cloud-config.html
2014-10-30 11:48:02 +00:00

1252 lines
64 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.1">
<title>Spring Cloud Config</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic|Noto+Serif:400,400italic,700,700italic|Droid+Sans+Mono:400">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Remove the comments around the @import statement below when using this as a custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic|Noto+Serif:400,400italic,700,700italic|Droid+Sans+Mono:400";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body{margin:0}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
#map_canvas img,#map_canvas embed,#map_canvas object,.map_canvas img,.map_canvas embed,.map_canvas object{max-width:none!important}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
.antialiased,body{-webkit-font-smoothing:antialiased}
img{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.no-bullet{list-style:none}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite:before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
.clearfix:after,.float-group:after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
.keyseq{color:rgba(51,51,51,.8)}
kbd{display:inline-block;color:rgba(0,0,0,.8);font-size:.75em;line-height:1.4;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:-.15em .15em 0 .15em;padding:.2em .6em .2em .5em;vertical-align:middle;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menu{color:rgba(0,0,0,.8)}
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
b.button:before{content:"[";padding:0 3px 0 2px}
b.button:after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
#content{margin-top:1.25em}
#content:before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber:after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]:before{display:block}
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.05em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.spread{width:100%}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-check-square-o:first-child,ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1{padding-right:.75em;font-weight:bold}
td.hdlist1,td.hdlist2{vertical-align:top}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none}
span.footnote,span.footnoteref{vertical-align:super;font-size:.875em}
span.footnote a,span.footnoteref a{text-decoration:none}
span.footnote a:active,span.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em;line-height:1.3;font-size:.875em;margin-left:1.2em;text-indent:-1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
h1,h2{letter-spacing:-.01em}
dt,th.tableblock,td.content{text-rendering:optimizeLegibility}
p,td.content{letter-spacing:-.01em}
p strong,td.content strong{letter-spacing:-.005em}
p,blockquote,dt,td.content{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]:after{content:" (" attr(title) ")"}
pre,blockquote,tr,img{page-break-inside:avoid}
thead{display:table-header-group}
img{max-width:100%!important}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span:before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]:before{display:block}
#footer{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
</style>
</head>
<body class="article">
<div id="header">
<h1>Spring Cloud Config</h1>
<div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_quick_start">Quick Start</a>
<ul class="sectlevel2">
<li><a href="#_client_side_usage">Client Side Usage</a></li>
</ul>
</li>
<li><a href="#_spring_cloud_config_server">Spring Cloud Config Server</a>
<ul class="sectlevel2">
<li><a href="#_security">Security</a></li>
<li><a href="#_encryption_and_decryption">Encryption and Decryption</a></li>
<li><a href="#_key_management">Key Management</a></li>
<li><a href="#_creating_a_key_store_for_testing">Creating a Key Store for Testing</a></li>
<li><a href="#_embedding_the_config_server">Embedding the Config Server</a></li>
</ul>
</li>
<li><a href="#_spring_cloud_config_client">Spring Cloud Config Client</a>
<ul class="sectlevel2">
<li><a href="#_config_first_bootstrap">Config First Bootstrap</a></li>
<li><a href="#_eureka_first_bootstrap">Eureka First Bootstrap</a></li>
<li><a href="#_environment_changes">Environment Changes</a></li>
<li><a href="#_refresh_scope">Refresh Scope</a></li>
<li><a href="#_encryption_and_decryption_2">Encryption and Decryption</a></li>
<li><a href="#_endpoints">Endpoints</a></li>
<li><a href="#_locating_remote_configuration_resources">Locating Remote Configuration Resources</a></li>
<li><a href="#_the_bootstrap_application_context">The Bootstrap Application Context</a></li>
<li><a href="#_application_context_hierarchies">Application Context Hierarchies</a></li>
<li><a href="#customizing-bootstrap-properties">Changing the Location of Bootstrap Properties</a></li>
<li><a href="#_customizing_the_bootstrap_configuration">Customizing the Bootstrap Configuration</a></li>
<li><a href="#customizing-bootstrap-property-sources">Customizing the Bootstrap Property Sources</a></li>
<li><a href="#_security_2">Security</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With the Config Server you have a central place to manage external properties for applications across all environments. The concepts on both client and server map identically to the Spring <code>Environment</code> and <code>PropertySource</code> abstractions, so they fit very well with Spring applications, but can be used with any application running in any language. As an application moves through the deployment pipeline from dev to test and into production you can manage the configuration between those environments and be certain that applications have everything they need to run when they migrate. The default implementation of the server storage backend uses git so it easily supports labelled versions of configuration environments, as well as being accessible to a wide range of tooling for managing the content. It is easy to add alternative implementations and plug them in with Spring configuration.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_quick_start">Quick Start</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Start the server:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ cd spring-cloud-config-server
$ mvn spring-boot:run</pre>
</div>
</div>
<div class="paragraph">
<p>The server is a Spring Boot application so you can build the jar file
and run that (<code>java -jar &#8230;&#8203;</code>) or pull it down from a Maven
repository. Then try it out as a client:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ curl localhost:8888/foo/development
{"name":"development","label":"master","propertySources":[
{"name":"https://github.com/scratches/config-repo/foo-development.properties","source":{"bar":"spam"}},
{"name":"https://github.com/scratches/config-repo/foo.properties","source":{"foo":"bar"}}
]}</pre>
</div>
</div>
<div class="paragraph">
<p>The default strategy for locating property sources is to clone a git
repository (at "spring.cloud.config.server.uri") and use it to
initialize a mini <code>SpringApplication</code>. The mini-application&#8217;s
<code>Environment</code> is used to enumerate property sources and publish them
via a JSON endpoint. The service has resources in the form:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties</pre>
</div>
</div>
<div class="paragraph">
<p>where the "application" is injected as the "spring.config.name" in the
<code>SpringApplication</code> (i.e. what is normally "application" in a regular
Spring Boot app), "profile" is an active profile (or comma-separated
list of properties), and "label" is an optional git label (defaults to
"master".) The YAML and properties forms are coalesced into a single
map, even if the origin of the values (reflected in the
"propertySources" of the "standard" form) has multiple sources.</p>
</div>
<div class="sect2">
<h3 id="_client_side_usage">Client Side Usage</h3>
<div class="paragraph">
<p>To use these features in an application, just build it as a Spring
Boot application that depends on spring-cloud-config-client (e.g. see
the test cases for the config-client, or the sample app). The most
convenient way to add the dependency is via a Spring Boot starter
<code>org.springframework.cloud:spring-cloud-starter</code>. There is also a
parent pom and BOM (<code>spring-cloud-starters</code>) for Maven users and a
Spring IO version management properties file for Gradle and Spring CLI
users. Example Maven configuration:</p>
</div>
<div class="listingblock">
<div class="title">pom.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;parent&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
&lt;version&gt;1.1.7.RELEASE&lt;/version&gt;
&lt;relativePath /&gt; &lt;!-- lookup parent from repository --&gt;
&lt;/parent&gt;
&lt;dependencyManagement&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-starters&lt;/artifactId&gt;
&lt;version&gt;1.0.0.BUILD-SNAPSHOT&lt;/version&gt;
&lt;type&gt;pom&lt;/type&gt;
&lt;scope&gt;import&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;/dependencyManagement&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-starter&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;
&lt;!-- repositories also needed for snapshots and milestones --&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then you can create a standard Spring Boot application, like this simple HTTP server:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>@Configuration
@EnableAutoConfiguration
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello World!";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}</pre>
</div>
</div>
<div class="paragraph">
<p>When it runs it will pick up the external configuration from the
default local config server on port 8888 if it is running. To modify
the startup behaviour you can change the location of the config server
using <code>bootstrap.properties</code> (like <code>application.properties</code> but for
the bootstrap phase of an application context), e.g.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>spring.cloud.config.uri: http://myconfigserver.com</pre>
</div>
</div>
<div class="paragraph">
<p>The bootstrap properties will show up in the <code>/env</code> endpoint as a
high-priority property source, e.g.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ curl localhost:8080/env
{
"profiles":[],
"configService:https://github.com/scratches/config-repo/bar.properties":{"foo":"bar"},
"servletContextInitParams":{},
"systemProperties":{...},
...
}</pre>
</div>
</div>
<div class="paragraph">
<p>(a property source called "configService:&lt;URL of remote
repository&gt;/&lt;file name&gt;" contains the property "foo" with value
"bar" and is highest priority).</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_spring_cloud_config_server">Spring Cloud Config Server</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The Server provides an HTTP, resource-based API for external
configuration (name-value pairs, or equivalent YAML content). The
server is easily embeddable in a Spring Boot application using the
<code>@EnableConfigServer</code> annotation.</p>
</div>
<div class="sect2">
<h3 id="_security">Security</h3>
<div class="paragraph">
<p>You are free to secure your Config Server in any way that makes sense
to you (from physical network security to OAuth2 bearer
tokens), and Spring Security and Spring Boot make it easy to do pretty
much anything.</p>
</div>
<div class="paragraph">
<p>To use the default Spring Boot configured HTTP Basic security, just
include Spring Security on the classpath (e.g. through
<code>spring-boot-starter-security</code>). The default is a username of "user"
and a randomly generated password, which isn&#8217;t going to be very useful
in practice, so we recommend you configure the password (via
<code>security.user.password</code>) and encrypt it (see below for instructions
on how to do that).</p>
</div>
</div>
<div class="sect2">
<h3 id="_encryption_and_decryption">Encryption and Decryption</h3>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
<strong>Prerequisites:</strong> to use the encryption and decryption features
you need the full-strength JCE installed in your JVM (it&#8217;s not there by default).
You can download the "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files"
from Oracle, and follow instructions for installation (essentially replace the 2 policy files
in the JRE lib/security directory with the ones that you downloaded).
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The server exposes <code>/encrypt</code> and <code>/decrypt</code> endpoints (on the
assumption that these will be secured and only accessed by authorized
agents). If the remote property sources contain encryted content
(values starting with <code>{cipher}</code>) they will be decrypted before
sending to clients over HTTP. The main advantage of this set up is
that the property values don&#8217;t have to be in plain text when they are
"at rest" (e.g. in a git repository). If a value cannot be decrypted
it is replaced with an empty string, largely to prevent cipher text
being used as a password in Spring Boot autconfigured HTTP basic.</p>
</div>
<div class="paragraph">
<p>If you are setting up a remote config repository for config client
applications it might contain an <code>application.yml</code> like this, for
instance:</p>
</div>
<div class="listingblock">
<div class="title">application.yml</div>
<div class="content">
<pre>spring:
datasource:
username: dbuser
password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ</pre>
</div>
</div>
<div class="paragraph">
<p>You can safely push this plain text to a shared git repository and the
secret password is protected.</p>
</div>
<div class="paragraph">
<p>If you are editing a remote config file you can use the Config Server
to encrypt values by POSTing to the <code>/encrypt</code> endpoint, e.g.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ curl localhost:8888/encrypt -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda</pre>
</div>
</div>
<div class="paragraph">
<p>The inverse operation is also available via <code>/decrypt</code> (provided the server is
configured with a symmetric key or a full key pair):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ curl localhost:8888/decrypt -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret</pre>
</div>
</div>
<div class="paragraph">
<p>Take the encypted value and add the <code>{cipher}</code> prefix before you put
it in the YAML or properties file, and before you commit and push it
to a remote, potentially insecure store.</p>
</div>
<div class="paragraph">
<p>The <code>spring</code> command line client (with Spring Cloud CLI extensions
installed) can also be used to encrypt and decrypt, e.g.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ spring encrypt mysecret --key foo
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
$ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret</pre>
</div>
</div>
<div class="paragraph">
<p>To use a key in a file (e.g. an RSA public key for encyption) prepend
the key value with "@" and provide the file path, e.g.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...</pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_key_management">Key Management</h3>
<div class="paragraph">
<p>The Config Server can use a symmetric (shared) key or an asymmetric
one (RSA key pair). The asymmetric choice is superior in terms of
security, but it is often more convenient to use a symmetric key since
it is just a single property value to configure.</p>
</div>
<div class="paragraph">
<p>To configure a symmetric key you just need to set <code>encrypt.key</code> to a
secret String (or use an enviroment variable <code>ENCRYPT_KEY</code> to keep it
out of plain text configuration files). You can also POST a key value
to the <code>/key</code> endpoint (but that won&#8217;t change any existing encrypted
values in remote repositories).</p>
</div>
<div class="paragraph">
<p>To configure an asymmetric key you can either set the key as a
PEM-encoded text value (in <code>encrypt.key</code>), or via a keystore (e.g. as
created by the <code>keytool</code> utility that comes with the JDK). The
keystore properties are <code>encrypt.keyStore.*</code> with <code>*</code> equal to</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>location</code> (a <code>Resource</code> location),</p>
</li>
<li>
<p><code>password</code> (to unlock the keystore) and</p>
</li>
<li>
<p><code>alias</code> (to identify which key in the store is to be
used).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The encryption is done with the public key, and a private key is
needed for decryption. Thus in principle you can configure only the
public key in the server if you only want to do encryption (and are
prepared to decrypt the values yourself locally with the private
key). In practice you might not want to do that because it spreads the
key management process around all the clients, instead of
concentrating it in the server. On the other hand it&#8217;s a useful option
if your config server really is relatively insecure and only a
handful of clients need the encrypted properties.</p>
</div>
</div>
<div class="sect2">
<h3 id="_creating_a_key_store_for_testing">Creating a Key Store for Testing</h3>
<div class="paragraph">
<p>To create a keystore for testing you can do something like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ keytool -genkeypair -alias mytestkey -keyalg RSA \
-dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
-keypass changeme -keystore server.jks -storepass letmein</pre>
</div>
</div>
<div class="paragraph">
<p>Put the <code>server.jks</code> file in the classpath (for instance) and then in
your <code>application.yml</code> for the Config Server:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>encrypt:
keyStore:
location: classpath:/server.jks
alias: mytestkey
password: letmein</pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_embedding_the_config_server">Embedding the Config Server</h3>
<div class="paragraph">
<p>The Config Server runs best as a standalone application, but if you
need to you can embed it in another application. Just use the
<code>@EnableConfigServer</code> annotation and (optionally) set
<code>spring.cloud.config.server.prefix</code> to a path prefix, e.g. "/config",
to serve the resources under a prefix. The prefix should start but not
end with a "/". It is applied to the <code>@RequestMappings</code> in the Config
Server (i.e. underneath the Spring Boot prefixes <code>server.servletPath</code>
and <code>server.contextPath</code>).</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_spring_cloud_config_client">Spring Cloud Config Client</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A Spring Boot application can take immediate advantage of the Spring
Config Server (or other external property sources provided by the
application developer), and it will also pick up some additional
useful features related to <code>Environment</code> change events.</p>
</div>
<div class="sect2">
<h3 id="_config_first_bootstrap">Config First Bootstrap</h3>
<div class="paragraph">
<p>This is the default behaviour for any application wich has the Spring
Cloud Config Client on the classpath. When a config client starts up
it binds to the Config Server (via the bootstrap configuration
property <code>spring.cloud.config.uri</code>) and initializes Spring
<code>Environment</code> with remote property sources.</p>
</div>
<div class="paragraph">
<p>The net result of this is that all client apps that want to consume
the Config Server need a <code>bootstrap.yml</code> (or an environment variable)
with the server address in <code>spring.cloud.config.uri</code> (defaults to
"http://localhost:8888").</p>
</div>
</div>
<div class="sect2">
<h3 id="_eureka_first_bootstrap">Eureka First Bootstrap</h3>
<div class="paragraph">
<p>If you are using Spring Cloud Netflix and Eureka Service Discovery,
then you can have the Config Server register with Eureka if you want
to, but in the default "Config First" mode, clients won&#8217;t be able to
take advantage of the registration.</p>
</div>
<div class="paragraph">
<p>If you prefer to use Eureka to locate the Config Server, you can do
that by setting <code>spring.cloud.config.discovery.enabled=true</code> (default
"false"). The net result of that is that client apps all need a
<code>bootstrap.yml</code> (or an environment variable) with the Eureka server
address, e.g. in <code>eureka.client.serviceUrl.defaultZone</code>. The price
for using this option is an extra network round trip on start up to
locate the service registration. The benefit is that the Config Server
can change its co-ordinates, as long as Eureka is a fixed point.</p>
</div>
</div>
<div class="sect2">
<h3 id="_environment_changes">Environment Changes</h3>
<div class="paragraph">
<p>The application will listen for an <code>EnvironmentChangedEvent</code> and react
to the change in a couple of standard ways (additional
<code>ApplicationListeners</code> can be added as <code>@Beans</code> by the user in the
normal way). When an <code>EnvironmentChangedEvent</code> is observed it will
have a list of key values that have changed, and the application will
use those to:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Re-bind any <code>@ConfigurationProperties</code> beans in the context</p>
</li>
<li>
<p>Set the logger levels for any properties in <code>logging.level.*</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This covers a large class of refresh use cases, and you can verify the
changes by visiting the <code>/configprops</code> endpoint (normal Spring Boot
Actuator feature). For instance a <code>DataSource</code> can have its
<code>maxPoolSize</code> changed at runtime (the default <code>DataSource</code> created by
Spring Boot is an <code>@ConfigurationProperties</code> bean) and grow capacity
dynamically. It does not cover another large class of use cases, where
you need more control over the refresh, and where you need a
configuration change to be atomic over the whole
<code>ApplicationContext</code>. To address those concerns we have
<code>@RefreshScope</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_refresh_scope">Refresh Scope</h3>
<div class="paragraph">
<p>A Spring <code>@Bean</code> that is marked as <code>@RefreshScope</code> will get special
treatment when there is a configuration change. This addresses the
problem of stateful beans that only get their configuration injected
when they are initialized. For instance if a <code>DataSource</code> has open
connections when the database URL is changed via the <code>Environment</code>, we
probably want the holders of those connections to be able to complete
what they are doing. Then the next time someone borrows a connection
from the pool he gets one with the new URL.</p>
</div>
<div class="paragraph">
<p>Refresh scope beans are lazy proxies that initialize when they are
used (i.e. when a method is called), and the scope acts as a cache of
initialized values. To force a bean to re-initialize on the next
method call you just need to invalidate its cache entry.</p>
</div>
<div class="paragraph">
<p>The <code>RefreshScope</code> is a bean in the context and it has a public method
<code>refreshAll()</code> to refresh all beans in the scope by clearing the
target cache. There is also a <code>refresh(String)</code> method to refresh an
individual bean by name. This functionality is exposed in the
<code>/refresh</code> endpoint (over HTTP or JMX).</p>
</div>
</div>
<div class="sect2">
<h3 id="_encryption_and_decryption_2">Encryption and Decryption</h3>
<div class="paragraph">
<p>The Config Client has an <code>Environment</code> pre-processor for decrypting
property values locally. It follows the same rules as the Config
Server, and has the same external configuration via <code>encrypt.*</code>. Thus
you can use encrypted values in the form <code>{cipher}*</code> and as long as
there is a valid key then they will be decrypted before the main
application context gets the <code>Environment</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_endpoints">Endpoints</h3>
<div class="paragraph">
<p>For a Spring Boot Actuator application there are some additional management endpoints:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>POST to <code>/env</code> to update the <code>Environment</code> and rebind <code>@ConfigurationProperties</code> and log levels</p>
</li>
<li>
<p><code>/refresh</code> for re-loading the boot strap context and refreshing the <code>@RefreshScope</code> beans</p>
</li>
<li>
<p><code>/restart</code> for closing the <code>ApplicationContext</code> and restarting it (disabled by default)</p>
</li>
<li>
<p><code>/pause</code> and <code>/resume</code> for calling the <code>Lifecycle</code> methods (<code>stop()</code> and <code>start()</code> on the <code>ApplicationContext</code>)</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_locating_remote_configuration_resources">Locating Remote Configuration Resources</h3>
<div class="paragraph">
<p>The Config Service serves property sources from <code>/{name}/{env}/{label}</code>, where the default bindings are</p>
</div>
<div class="ulist">
<ul>
<li>
<p>"name" = <code>${spring.application.name}</code></p>
</li>
<li>
<p>"env" = <code>${spring.profiles.active}</code> (actually <code>Environment.getActiveProfiles()</code>)</p>
</li>
<li>
<p>"label" = "master"</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>All of them can be overridden by setting <code>spring.cloud.config.*</code>
(where <code>*</code> is "name", "env" or "label"). The "label" is useful for
rolling back to previous versions of configuration; with the default
Config Server implementation it can be a git label, branch name or
commit id.</p>
</div>
</div>
<div class="sect2">
<h3 id="_the_bootstrap_application_context">The Bootstrap Application Context</h3>
<div class="paragraph">
<p>The Config Client operates by creating a "bootstrap" application
context, which is a parent context for the main application. Out of
the box it is responsible for loading configuration properties from
the Config Server, and also decrypting properties in the local
external configuration files. The two contexts share an <code>Environment</code>
which is the source of external properties for any Spring
application. Bootstrap properties are added with high precedence, so
they cannot be overridden by local configuration.</p>
</div>
<div class="paragraph">
<p>The bootstrap context uses a different convention for locating
external configuration than the main application context, so instead
of <code>application.yml</code> (or <code>.properties</code>) you use <code>bootstrap.yml</code>,
keeping the external configuration for bootstrap and main context
nicely separate. Example:</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre>spring:
application:
name: foo
cloud:
config:
uri: ${SPRING_CONFIG_URI:http://localhost:8888}</pre>
</div>
</div>
<div class="paragraph">
<p>It is a good idea to set the <code>spring.application.name</code> (in
<code>bootstrap.yml</code> or <code>application.yml</code>) if your application needs any
application-specific configuration from the server.</p>
</div>
<div class="paragraph">
<p>You can disable the bootstrap process completely by setting
<code>spring.cloud.bootstrap.enabled=false</code> (e.g. in System properties).</p>
</div>
</div>
<div class="sect2">
<h3 id="_application_context_hierarchies">Application Context Hierarchies</h3>
<div class="paragraph">
<p>If you build an application context from <code>SpringApplication</code> or
<code>SpringApplicationBuilder</code>, then the Bootstrap context is added as a
parent to that context. It is a feature of Spring that child contexts
inherit property sources and profiles from their parent, so the "main"
application context will contain additional property sources, compared
to building the same context without Spring Cloud Config. The
additional property sources are:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>"bootstrap": an optional <code>CompositePropertySource</code> appears with high
priority if any <code>PropertySourceLocators</code> are found in the Bootstrap
context, and they have non-empty properties. An example would be
properties from the Spring Cloud Config Server. See
<a href="#customizing-bootstrap-property-sources">below</a> for instructions
on how to customize the contents of this property source.</p>
</li>
<li>
<p>"applicationConfig: [classpath:bootstrap.yml]" (and friends if
Spring profiles are active). If you have a <code>bootstrap.yml</code> (or
properties) then those properties are used to configure the Bootstrap
context, and then they get added to the child context when its parent
is set. They have lower precedence than the <code>application.yml</code> (or
properties) and any other property sources that are added to the child
as a normal part of the process of creating a Spring Boot
application. See <a href="#customizing-bootstrap-properties">below</a> for
instructions on how to customize the contents of these property
sources.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Because of the ordering rules of property sources the "bootstrap"
entries take precedence, but note that these do not contain any data
from <code>bootstrap.yml</code>, which has very low precedence, but can be used
to set defaults.</p>
</div>
<div class="paragraph">
<p>You can extend the context hierarchy by simply setting the parent
context of any <code>ApplicationContext</code> you create, e.g. using its own
interface, or with the <code>SpringApplicationBuilder</code> convenience methods
(<code>parent()</code>, <code>child()</code> and <code>sibling()</code>). Note that the
<code>SpringApplicationBuilder</code> allows you to share an <code>Environment</code>
amongst the whole hierarchy, but that is not the default. Thus,
sibling contexts in particular do not need to have the same profiles
or property sources, even though they will share common things with
their parent. Every context in the hierarchy will have its own
"bootstrap" property source (possibly empty) to avoid promoting values
inadvertently from parents down to their descendants. Every context in
the hierarchy can also (in principle) have a different
<code>spring.application.name</code> and hence a different remote property source
if there is a Config Server. Remember that properties from a child
context override those in the parent.</p>
</div>
</div>
<div class="sect2">
<h3 id="customizing-bootstrap-properties">Changing the Location of Bootstrap Properties</h3>
<div class="paragraph">
<p>The <code>bootstrap.yml</code> (or <code>.properties) location can be specified using
`spring.cloud.bootstrap.name</code> (default "bootstrap") or
<code>spring.cloud.bootstrap.location</code> (default empty), e.g. in System
properties. Those properties behave like the <code>spring.config.*</code>
variants with the same name, in fact they are used to set up the
bootstrap <code>ApplicationContext</code> by setting those properties in its
<code>Environment</code>. If there is an active profile (from
<code>spring.profiles.active</code> or through the <code>Environment</code> API in the
context you are building) then properties in that profile will be
loaded as well, just like in a regular Spring Boot app, e.g. from
<code>bootstrap-development.properties</code> for a "development" profile.</p>
</div>
</div>
<div class="sect2">
<h3 id="_customizing_the_bootstrap_configuration">Customizing the Bootstrap Configuration</h3>
<div class="paragraph">
<p>The bootstrap context can be trained to do anything you like by adding
entries to <code>/META-INF/spring.factories</code> under the key
<code>org.springframework.cloud.bootstrap.BootstrapConfiguration</code>. This is
a comma-separated list of Spring <code>@Configuration</code> classes which will
be used to create the context. Any beans that you want to be available
to the main application context for autowiring can be created here,
and also there is a special contract for <code>@Beans</code> of type
<code>ApplicationContextInitializer</code>.</p>
</div>
<div class="paragraph">
<p>The bootstrap process ends by injecting initializers into the main
<code>SpringApplication</code> instance (i.e. the normal Spring Boot startup
sequence, whether it is running as a standalone app or deployed in an
application server). First a bootstrap context is created from the
classes found in <code>spring.factories</code> and then all <code>@Beans</code> of type
<code>ApplicationContextInitializer</code> are added to the main
<code>SpringApplication</code> before it is started.</p>
</div>
</div>
<div class="sect2">
<h3 id="customizing-bootstrap-property-sources">Customizing the Bootstrap Property Sources</h3>
<div class="paragraph">
<p>The default property source for external configuration added by the
bootstrap process is the Config Server, but you can add additional
sources by adding beans of type <code>PropertySourceLocator</code> to the
bootstrap context (via <code>spring.factories</code>). You could use this to
insert additional properties from a different server, or from a
database, for instance.</p>
</div>
<div class="paragraph">
<p>As an example, consider the following trivial custom locator:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {
@Override
public PropertySource&lt;?&gt; locate(Environment environment) {
return new MapPropertySource("customProperty",
Collections.&lt;String, Object&gt;singletonMap("property.from.sample.custom.source", "worked as intended"));
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>Environment</code> that is passed in is the one for the
<code>ApplicationContext</code> about to be created, i.e. the one that we are
supplying additional property sources for. It will already have its
normal Spring Boot-provided property sources, so you can use those to
locate a property source specific to this <code>Environment</code> (e.g. by
keying it on the <code>spring.application.name</code>, as is done in the default
Config Server property source locator).</p>
</div>
<div class="paragraph">
<p>If you create a jar with this class in it and then add a
<code>META-INF/spring.factories</code> containing:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator</pre>
</div>
</div>
<div class="paragraph">
<p>then the "customProperty" <code>PropertySource</code> will show up in any
application that includes that jar on its classpath.</p>
</div>
</div>
<div class="sect2">
<h3 id="_security_2">Security</h3>
<div class="paragraph">
<p>If you use HTTP Basic security on the server then clients just need to
know the password (and username if it isn&#8217;t the default). You can do
that via the config server URI, or via separate username and password
properties, e.g.</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre>spring:
cloud:
config:
uri: https://user:secret@myconfig.mycompany.com</pre>
</div>
</div>
<div class="paragraph">
<p>or</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre>spring:
cloud:
config:
uri: https://myconfig.mycompany.com
username: user
password: secret</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>spring.cloud.config.password</code> and <code>spring.cloud.config.username</code>
values override anything that is provided in the URI.</p>
</div>
<div class="paragraph">
<p>If you deploy your apps on Cloud Foundry then the best way to provide
the password is through service credentials, e.g. in the URI, since
then it doesn&#8217;t even need to be in a config file. An example which
works locally and for a user-provided service on Cloud Foundry named
"configserver":</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre>spring:
cloud:
config:
uri: ${vcap.services.configserver.credentials.uri:http://user:password@localhost:8888}</pre>
</div>
</div>
<div class="paragraph">
<p>If you use another form of security you might need to provide a
<code>RestTemplate</code> to the <code>ConfigServicePropertySourceLocator</code> (e.g. by
grabbing it in the bootstrap context and injecting one).</p>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2014-10-30 11:46:25 UTC
</div>
</div>
</body>
</html>