I think you need a regular function here instead of a regular expression. The problem is that pure regular expressions can't match arbitrarily nested recursive patterns. So, they aren't much use for track matching openers and closers.
Instead, write a function to make a pass over the input string tracking the openers in a LIFO stack (just append to a regular python list) and then match closers as you find them (popping off the most recent corresponding opener):
import re
braces = re.compile(r'(\${)|(})')
def substitute(s, **env):
openers = []
pos = 0
while 1:
mo = braces.search(s, pos)
if mo is None:
break
opener, closer = mo.groups()
if opener:
openers.append(mo.start())
pos = mo.end() + 1
continue
start = openers.pop()
end = mo.end()
body = s[start+2 : end-1]
s = s[:start] + env[body] + s[end:]
return s
print substitute('Return to ${home_${path}} for further ${action}',
home_world='earth',
home_state='kansas',
path='state',
action='orders')
${}in a string like${home} ${path}?